我刚刚开始使用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传递给每个函数调用以填充其结果。
答案 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
注意:它弄乱了索引(最左边)。我还没弄明白如何防止这种情况(其他人?),但大多数情况下它可能并不重要。