将第一行添加到空数据时,行号有所不同(NA与1)

时间:2018-07-17 17:45:13

标签: r dataframe

我想了解为什么这两种索引空data.frame的方法会导致将NA行号分配给仅 的第一行:

方法1:

df <- data.frame(Number=numeric(), Text=character(), stringsAsFactors = FALSE)
df[1,]$Number <- 123456
df[1,]$Text <- "abcdef"
df[2,]$Number <- 456789
df[2,]$Text <- "abcdef"

输出1:

> df
   Number   Text
NA 123456 abcdef
2  456789 abcdef

方法2:

df <- data.frame(Number=numeric(), Text=character(), stringsAsFactors = FALSE)
df[1,1] <- 123456
df[1,2] <- "abcdef"
df[2,1] <- 456789
df[2,2] <- "abcdef"

输出2:

> df
  Number   Text
1 123456 abcdef
2 456789 abcdef

我看到的唯一区别是,第一种方法使用列名而不是列号访问data.frame,但是我不明白为什么这会导致产生NA行号只能分配给第一个观测值,因为从第二行开始行号似乎可以正常工作。

1 个答案:

答案 0 :(得分:4)

好吧,这个答案最重要的部分是应该避免这样的代码。将数据逐行R地添加到data.frame效率非常低(请参阅R Inferno的第2圈)。几乎总是有更好的方法来执行此操作,具体取决于您正在执行的操作。

但是要了解这里发生的情况。所有这些都归结为$.data.frame<-[.data.frame[<-.data.frame函数。在第一种情况下,使用

df[1,]$Number <- 123456

您首先执行的是调用[<-.data.frame的子集。当您请求不存在的data.frame的一行时,您会得到一堆针对所有内容(包括行名)的NA值。因此,现在您有了一个空的data.frame,在列和行名中具有NA值。现在,您调用$<-.data.frame来更新Number列。您不更新行号。然后将这个新值传递给[<-.data.frame,以将其合并回data.frame。运行此命令时,它将检查以确保没有重复的行名。对于第一行,由于只有一行并且它的名称为NA,因此将保留该名称。但是,当名称重复时,该函数将这些值替换为行号的索引。这就是为什么第一行得到一个NA的原因,但是当它尝试添加下一行时,它再次尝试了NA,但是看到它是重复的,因此必须选择一个新名称。 (看看先尝试df[1:2,]$Number <- 123456然后尝试df[3,]$Number <- 456789会发生什么情况)

另一方面,当您这样做

df[1,1] <- 123456

这不会首先创建子集来创建缺少行名的行。您可以直接跳过$.data.frame<-[.data.frame进行分配。在这种情况下,它不必合并到具有NA行名称的新行中,它可以立即创建该行并分配一个行名称。这只是调用赋值运算符而必须先进行提取的一种特殊属性。您可以将调试器与debug(`[<-.data.frame`)配合使用,以查看确切的过程。

因此,第一种方法基本上执行三个步骤:1)扩展df[1,],2)更改数字列的值,然后3)将新值合并回df[1,]。第二种方法跳过第一种方法,而只是将值直接合并到df[1,]中。真正的区别在于,每个函数如何为尚不存在的行选择行名。