2011-03-08 38 views
54

我剛剛以R開頭,並遇到一個奇怪的行爲:將第一行插入空數據框時,原始列名會丟失。R:將行添加到空數據框時丟失列名

例如:

a<-data.frame(one = numeric(0), two = numeric(0)) 
a 
#[1] one two 
#<0 rows> (or 0-length row.names) 
names(a) 
#[1] "one" "two" 
a<-rbind(a, c(5,6)) 
a 
# X5 X6 
#1 5 6 
names(a) 
#[1] "X5" "X6" 

正如你所看到的,列名一個和被X5X6取代。

請問有人可以告訴我爲什麼會發生這種情況,是否有正確的方法可以做到這一點而不會丟失列名?

霰彈槍的解決方案是將名稱保存在輔助矢量中,然後在數據框上完成工作時將其添加回來。

由於

上下文:

我創建了收集一些數據並將它們作爲新行的數據幀接收到的作爲參數的函數。 我創建數據框,迭代我的數據源,將data.frame傳遞給每個函數調用以填充其結果。

回答

28

個的rbind幫助頁面指定:

對於 'cbind'( 'rbind'),零 長度的載體(包括 'NULL')將被忽略 除非結果將具有零行 (列),用於S兼容性。 (零程度矩陣不發生在 S3和R.不忽略)

所以,其實,a在你rbind指令忽略。不能完全忽略了,現在看來,因爲它是一個數據幀的rbind功能被稱爲rbind.data.frame

rbind.data.frame(c(5,6)) 
# X5 X6 
#1 5 6 

也許一個插入行的方式可以是:

a[nrow(a)+1,] <- c(5,6) 
a 
# one two 
#1 5 6 

但可能會出現根據您的代碼更好地實現這一點。

8

解決方法將是:

a <- rbind(a, data.frame(one = 5, two = 6)) 

?rbind指出合併對象要求相匹配的名字:

然後它以 列的類從所述第一數據幀,並 匹配由列名稱(而不是 按位置)

+0

我認爲在你的代碼中的'了''裏面是rbind'忽略,所以它其實就相當於一個'< - data.frame(一個= 5,兩個= 6)'。但我可能是錯的。 – juba

+0

+1我通常使用這種方法 - 請注意,您可以簡單地將'a'初始化爲空向量:'a < - c()'。 –

+0

@juba,可能是這種情況,因爲data.frame'a'是空的。 –

7

FWIW,替代設計可能有你的功能建設載體爲兩列,而不是rbinding到數據幀:

ones <- c() 
twos <- c() 

修改向量的功能:

ones <- append(ones, 5) 
twos <- append(twos, 6) 

重複根據需要,然後創建您的data.frame一次去:

a <- data.frame(one=ones, two=twos) 
+1

非常有幫助。也許不是簡潔,但數據流是一個黑盒子少一點。 – Andrew

+0

確實是一個很好的答案。但它似乎非常「不是R」。在構建data.frame時,首先需要對所有內容進行*循環,而row操作符是R的主力。也許使用@juba的答案,但在末尾設置colname:'colnames(a)< - c(「一」, 「二」)'? – user989762

+0

這種方法的問題在於,您經常需要使用域名進行數據框的擴展。爲什麼r中這麼簡單的事情如此複雜...? – TMOTTM

7

幾乎surrende響起這個問題。

1)stringsAsFactor集創建數據幀FALSE或運行直接進入下一個問題

2)不使用rbind - 不知道爲什麼地球上它是搞亂列名。簡單地做這樣說:

df[nrow(df)+1,] <- c("d","gsgsgd",4)

df <- data.frame(a = character(0), b=character(0), c=numeric(0)) 

df[nrow(df)+1,] <- c("d","gsgsgd",4) 

#Warnmeldungen: 
#1: In `[<-.factor`(`*tmp*`, iseq, value = "d") : 
# invalid factor level, NAs generated 
#2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") : 
# invalid factor level, NAs generated 

df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F) 

df[nrow(df)+1,] <- c("d","gsgsgd",4) 

df 
# a  b c 
#1 d gsgsgd 4 
1

你可以這樣做:

給一個行初始數據幀

df=data.frame(matrix(nrow=1,ncol=length(newrow)) 

添加新行,並採取了NAS

newdf=na.omit(rbind(newrow,df)) 

但要小心你的新生沒有NA,否則它也會被刪除。

乾杯 阿古斯

-1

而是與numeric(0)構建data.frame我使用as.numeric(0)

a<-data.frame(one=as.numeric(0), two=as.numeric(0)) 

這產生了額外的初始行

a 
# one two 
#1 0 0 

綁定附加行

a<-rbind(a,c(5,6)) 
a 
# one two 
#1 0 0 
#2 5 6 

然後使用負索引,以去除第一(假的)行

a<-a[-1,] 
a 

# one two 
#2 5 6 

注意:它弄亂了th e指數(最左邊)。我還沒有想出如何防止(其他人?),但大部分時間可能無關緊要。

+0

大部分時間它可能會。 – TMOTTM

0

下面是一種使這種工作通用且重新輸入列名最少量的方法。這種方法不需要黑客NA或0

rs <- data.frame(i=numeric(), square=numeric(), cube=numeric()) 
for (i in 1:4) { 
    calc <- c(i, i^2, i^3) 
    # append calc to rs 
    names(calc) <- names(rs) 
    rs <- rbind(rs, as.list(calc)) 
} 

RS將有正確的名稱

> rs 
    i square cube 
1 1  1 1 
2 2  4 8 
3 3  9 27 
4 4  16 64 
> 

另一種方式來做到這一點更清潔的使用數據。表:

> df <- data.frame(a=numeric(0), b=numeric(0)) 
> rbind(df, list(1,2)) # column names are messed up 
> X1 X2 
> 1 1 2 

> df <- data.table(a=numeric(0), b=numeric(0)) 
> rbind(df, list(1,2)) # column names are preserved 
    a b 
1: 1 2 

請注意,data.table也是一個data.frame。

> class(df) 
"data.table" "data.frame" 
0

我使用下面溶液中的行添加到空數據幀:

d_dataset <- 
    data.frame(
    variable = character(), 
    before = numeric(), 
    after = numeric(), 
    stringsAsFactors = FALSE) 

d_dataset <- 
    rbind(
    d_dataset, 
     data.frame(
     variable = "test", 
     before = 9, 
     after = 12, 
     stringsAsFactors = FALSE)) 

print(d_dataset) 

variable before after 
1  test  9 12 

HTH。

親切的問候

喬治

相關問題