R:在向空数据帧添加行时丢失列名

时间:2011-03-08 11:01:11

标签: r dataframe names rbind

我刚刚开始使用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"

如您所见,列名称一个两个 X5 X6 替换。< / p>

有人可以告诉我为什么会发生这种情况,是否有正确的方法可以在不丢失列名的情况下执行此操作?

霰弹枪解决方案是将名称保存在辅助矢量中,然后在完成数据框处理后将其添加回来。

由于

上下文:

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

8 个答案:

答案 0 :(得分:33)

rbind帮助页面指定:

  

对于'cbind'('rbind'),向量为零   长度(包括'NULL')被忽略   除非结果为零行   (列),用于S兼容性。   (零范围矩阵不会出现在   在R中不会忽略S3。)

因此,事实上,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 :(得分:12)

几乎屈服于这个问题。

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

答案 2 :(得分:8)

解决方法是:

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

?rbind表示合并对象需要匹配名称:

  

然后它需要的类   来自第一个数据框的列,和   按名称匹配列(而不是   按位置)

答案 3 :(得分:7)

FWIW,另一种设计可能会让您的函数为两列构建向量,而不是重新绑定到数据框:

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

修改函数中的向量:

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

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

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

答案 4 :(得分: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"

答案 5 :(得分:1)

你可以这样做:

给初始数据框一行

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

添加新行并取出NAS

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

但要注意你的新手没有NA,否则它也会被删除。

干杯 Agus的

答案 6 :(得分:0)

我使用以下解决方案向空数据框添加一行:

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)   
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control input-sm'
            if field.required == True: 
                field.widget.attrs['required'] = ''
    class Meta:
        model = MyModel
        fields = ('my_field',)

HTH。

亲切的问候

乔治

答案 7 :(得分:-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

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