【问题标题】:How do you write to a data.frame when one of your columns contains strings?当您的列之一包含字符串时,您如何写入 data.frame?
【发布时间】:2015-12-13 00:54:14
【问题描述】:

我的问题包含this answer 中的代码变体。

如下代码:

d <- data.frame()
for (i in 1:3) {d <- rbind(d,c(i+i, i*i, i/1))}
d
str(d)

生成以下输出:

  X2 X1 X1.1
1  2  1    1
2  4  4    2
3  6  9    3

'data.frame':   3 obs. of  3 variables:
 $ X2  : num  2 4 6
 $ X1  : num  1 4 9
 $ X1.1: num  1 2 3

但是这段代码:

d2 <- data.frame()
for (i in 1:3) {d2 <- rbind(d2,c(i+i, i*i, i/1, "foo"))}
d2
str(d2)

生成错误的输出:

   X.2. X.1. X.1..1 X.foo.
1    2    1      1    foo
2 <NA> <NA>   <NA>    foo
3 <NA> <NA>   <NA>    foo

'data.frame':   3 obs. of  4 variables:
 $ X.2.  : Factor w/ 1 level "2": 1 NA NA
 $ X.1.  : Factor w/ 1 level "1": 1 NA NA
 $ X.1..1: Factor w/ 1 level "1": 1 NA NA
 $ X.foo.: Factor w/ 1 level "foo": 1 1 1

它也会产生错误:

Warning messages:
1: In `[<-.factor`(`*tmp*`, ri, value = "4") :
  invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, ri, value = "4") :
  invalid factor level, NA generated
3: In `[<-.factor`(`*tmp*`, ri, value = "2") :
  invalid factor level, NA generated
4: In `[<-.factor`(`*tmp*`, ri, value = "6") :
  invalid factor level, NA generated
5: In `[<-.factor`(`*tmp*`, ri, value = "9") :
  invalid factor level, NA generated
6: In `[<-.factor`(`*tmp*`, ri, value = "3") :
  invalid factor level, NA generated

我该如何解决这个问题?

【问题讨论】:

    标签: r for-loop dataframe


    【解决方案1】:

    不要使用for 循环逐行创建数据。相反,使用矢量化函数按列创建数据:

    x <- 1:3
    data.frame(a = x+x, b = x*x, c = x/1, d = "foo")
    #  a b c   d
    #1 2 1 1 foo
    #2 4 4 2 foo
    #3 6 9 3 foo
    

    在这种情况下,d 列是一个长度为 1 的向量,它正在被回收以适应其他列的长度。

    【讨论】:

      【解决方案2】:

      对代码的最小更改是将c 更改为data.frame

      d2 <- data.frame()
      for (i in 1:3) {d2 <- rbind(d2, data.frame(i+i, i*i, i/1, "foo"))}
      d2
      str(d2)
      

      但总的来说矢量化方法更好。

      【讨论】:

        【解决方案3】:

        正如其他答案所提到的,在循环中使用连接是构建对象的一种不好的方法,因为它非常慢。

        但是,要解释为什么您的代码不起作用,请考虑 c 在这里做了什么:它构造了一个向量。但是,R 中的向量是同质容器,这意味着它们只能包含单一数据类型。

        在您的情况下,这会导致数字被强制转换为字符串。因此,在循环的第一次迭代中,结果将是:

        c('2', '1', '1', 'foo')
        

        接下来,这个向量将作为新行连接到您的 data.frame 中。但是,默认情况下,字符向量在data.frame 内转换为factors。因此第一次迭代后的结果是以下data.frame:

        'data.frame':   1 obs. of  4 variables:
         $ X.2.  : Factor w/ 1 level "2": 1
         $ X.1.  : Factor w/ 1 level "1": 1
         $ X.1..1: Factor w/ 1 level "1": 1
         $ X.foo.: Factor w/ 1 level "foo": 1
        

        请注意,所有列都是因子。并且都只有一个级别:211foo。现在,当您在下一次循环迭代中连接另一行时,cbind 将新向量强制转换为已在d2 中找到的因子。对于'foo',这是可行的。但对于其他数字,这不起作用,因为这些因素不包含必要的水平。因此,强制的结果是NA

        【讨论】:

        • 这是对实际情况的很好的书面解释。我只需要一些关于如何从这里到那里的指导。
        猜你喜欢
        • 1970-01-01
        • 2021-07-28
        • 1970-01-01
        • 2010-11-28
        相关资源
        最近更新 更多