R:将行添加到空数据框时丢失列名

问题描述:

我刚刚以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传递给每个函数调用以填充其结果。

个的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 

但可能会出现根据您的代码更好地实现这一点。

解决方法将是:

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

?rbind指出合并对象要求相匹配的名字:

然后它以 列的类从所述第一数据帧,并 匹配由列名称(而不是 按位置)

+0

我认为在你的代码中的'了''里面是rbind'忽略,所以它其实就相当于一个' juba

+0

+1我通常使用这种方法 - 请注意,您可以简单地将'a'初始化为空向量:'a

+0

@juba,可能是这种情况,因为data.frame'a'是空的。 –

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) user989762

+0

这种方法的问题在于,您经常需要使用域名进行数据框的扩展。为什么r中这么简单的事情如此复杂...? – TMOTTM

几乎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 

你可以这样做:

给一个行初始数据帧

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

添加新行,并采取了NAS

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

但要小心你的新生没有NA,否则它也会被删除。

干杯 阿古斯

而是与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

下面是一种使这种工作通用且重新输入列名最少量的方法。这种方法不需要黑客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" 

我使用下面溶液中的行添加到空数据帧:

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。

亲切的问候

乔治