R:向空数据框中添加行时丢失列名


69

我只是从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"

如您所见,列名12X5X6代替。

有人可以告诉我为什么会这样吗,并且有正确的方法来做到这一点而又不会丢失列名吗?

shot弹枪解决方案是将名称保存在辅助向量中,然后在完成对数据帧的处理后将其重新添加。

谢谢

内容:

我创建了一个函数,该函数收集一些数据并将它们作为新行添加到作为参数接收的数据帧中。我创建数据框架,遍历数据源,将data.frame传递给每个函数调用以填充其结果。

Answers:


37

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

但是,根据您的代码,可能会有更好的方法。


1
如果你有不同的数据类型(character以及numeric例如)它是一个更好的主意使用list功能list("five",6)。否则它将把一切都理解为角色。
Untitpoi

13

几乎屈服于这个问题。

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

请注意,使用该方法,该c列不再是数字了!str(df)表示它是字符。
Untitpoi

8

解决方法是:

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

?rbind 声明合并对象需要匹配的名称:

然后,它从第一个数据框中获取列的类,并按名称(而不是按位置)匹配列


我认为您的代码中的a内部rbind被忽略了,因此实际上等效于a <- data.frame(one = 5, two = 6)。但是我可能是错的。
juba 2011年

+1我通常使用这种方法-请注意,您可以简单地将其初始化a为空向量:a <- c()
Prasad Chalasani 2011年

@juba,可能是这种情况,因为data.framea为空。
RomanLuštrik2011年

7

FWIW,一种替代设计可以让您的函数为两列构建向量,而不是绑定到数据帧:

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

修改函数中的向量:

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

根据需要重复,然后一次创建您的data.frame:

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

1
很有帮助。也许没有那么简洁,但是数据流却少了一些黑匣子。
安德鲁(Andrew)

确实是一个不错的答案。但是似乎非常“不是R”。当构建data.frame首先需要循环对所有的内容,而第一行经营者R.的驮马也许使用@juba答案,但设置colnames结尾:colnames(a) <- c("one","two")
user989762

这种方法的问题在于,您经常需要使用colname来扩展数据帧。为什么在r ...中如此简单的事情如此复杂?
TMOTTM 2015年

2

以下是使这项工作通用且最少重新键入列名的一种方法。此方法不需要破解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
> 

另一种更干净的方法是使用data.table:

> 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"

1

你可以这样做:

给初始数据帧一行

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

添加新行并取出NAS

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

但请注意,您的纽罗没有NA,否则也会被删除。

干杯阿格斯


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。

亲切的问候

格奥尔格


-1

而不是与构建data.framenumeric(0)我使用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

注意:它弄乱了索引(最左边)。我还没有想出如何防止这种情况(其他人吗?),但是大多数时候它可能并不重要。


2
大多数时候它可能会这样做。
TMOTTM 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.