当你的一个列包含字符串时,如何写入data.frame?

时间:2015-09-16 12:25:09

标签: r for-loop dataframe

我的问题包含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

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

不要使用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的向量,它被循环使用以适应其他列的长度。

答案 1 :(得分:1)

对代码进行的最小更改是将preg_match_all('~[a-z]+|\d+~i', $str, $matches); 更改为c

data.frame

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

答案 2 :(得分:1)

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

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

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

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

接下来,将此向量作为data.frame的新行连接。但是,默认情况下,字符向量在factor内转换为data.frame s。因此,第一次迭代后的结果是以下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