代码之家  ›  专栏  ›  技术社区  ›  NewUser

将第一行添加到空数据.frame时,行数不同(na与1)。

  •  6
  • NewUser  · 技术社区  · 8 年前

    我想知道这两种方法为什么为空索引 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
    

    我看到的唯一区别是第一个方法访问 数据帧 使用列名称而不是列号,但我不明白这会导致 分配给的行号 仅第一次观察 因为从第二排开始,行数似乎按预期工作。

    1 回复  |  直到 8 年前
        1
  •  4
  •   MrFlick    8 年前

    嗯,这个答案最重要的部分是应该避免这样的代码。将数据逐行添加到r中的data.frame是非常低效的(请参见 R Inferno )根据你到底在做什么,几乎总是有更好的方法来做到这一点。

    但要想知道这里发生了什么。所有这些都归结为 $.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<。- [数据帧] . 在这种情况下,它不必合并到具有NA行名称的新行中,它可以立即创建行并分配行名称。这只是调用赋值运算符的一个特殊属性,必须先进行提取。您可以使用 debug(`[<-.data.frame`) 看看到底是怎么回事。

    所以第一种方法基本上是做三个步骤:1)extact df[1,] ,2)更改数字列的值,然后3)将新值合并回 DF〔1〕 . 第二个方法跳过第一个步骤,直接将值合并到 DF〔1〕 . 真正的区别在于,每个函数如何为还不存在的行选择行名。