使用cbind从两个向量创建数据框

30

考虑以下 R 代码。

> x = cbind(c(10, 20), c("[]", "[]"), c("[[1,2]]","[[1,3]]"))
> x
     [,1] [,2] [,3]     
[1,] "10" "[]" "[[1,2]]"
[2,] "20" "[]" "[[1,3]]"

同样地

> x = rbind(c(10, "[]", "[[1,2]]"), c(20, "[]", "[[1,3]]"))
> x
     [,1] [,2] [,3]     
[1,] "10" "[]" "[[1,2]]"
[2,] "20" "[]" "[[1,3]]"

现在,我不想将整数1020转换为字符串。如何执行此操作而不进行任何转换?当然,我也想知道为什么会发生这种转换。我查看了cbind的帮助文档并尝试了谷歌搜索,但没有找到解决方法。我还相信,在某些情况下,R会将字符串转换为因子,我也不希望发生这种情况,尽管在这里似乎没有发生。


问题不在于 cbind,而在于 c。你需要更好地理解这个函数。 - IRTFM
2个回答

47

向量和矩阵只能是单一类型,对于向量的cbindrbind操作会生成矩阵。在这些情况下,数值将被提升为字符型以便存储所有的值。

(请注意,在您的rbind示例中,提升发生在c调用内部:)

> c(10, "[]", "[[1,2]]")
[1] "10"      "[]"      "[[1,2]]"
如果您想要一个矩形结构,其中列可以是不同类型的,则需要使用data.frame。以下任何一种方法都可以满足您的需求:
> x = data.frame(v1=c(10, 20), v2=c("[]", "[]"), v3=c("[[1,2]]","[[1,3]]"))
> x
  v1 v2      v3
1 10 [] [[1,2]]
2 20 [] [[1,3]]
> str(x)
'data.frame':   2 obs. of  3 variables:
 $ v1: num  10 20
 $ v2: Factor w/ 1 level "[]": 1 1
 $ v3: Factor w/ 2 levels "[[1,2]]","[[1,3]]": 1 2

或者(特别使用 data.frame 版本的 cbind

> x = cbind.data.frame(c(10, 20), c("[]", "[]"), c("[[1,2]]","[[1,3]]"))
> x
  c(10, 20) c("[]", "[]") c("[[1,2]]", "[[1,3]]")
1        10            []                 [[1,2]]
2        20            []                 [[1,3]]
> str(x)
'data.frame':   2 obs. of  3 variables:
 $ c(10, 20)              : num  10 20
 $ c("[]", "[]")          : Factor w/ 1 level "[]": 1 1
 $ c("[[1,2]]", "[[1,3]]"): Factor w/ 2 levels "[[1,2]]","[[1,3]]": 1 2

或者(使用cbind,但将第一个参数制作为data.frame,以便它与data.frame一样合并):

> x = cbind(data.frame(c(10, 20)), c("[]", "[]"), c("[[1,2]]","[[1,3]]"))
> x
  c.10..20. c("[]", "[]") c("[[1,2]]", "[[1,3]]")
1        10            []                 [[1,2]]
2        20            []                 [[1,3]]
> str(x)
'data.frame':   2 obs. of  3 variables:
 $ c.10..20.              : num  10 20
 $ c("[]", "[]")          : Factor w/ 1 level "[]": 1 1
 $ c("[[1,2]]", "[[1,3]]"): Factor w/ 2 levels "[[1,2]]","[[1,3]]": 1 2

感谢您提供详细的答案。我认为在这里不需要因子的属性,而且我记得它们可能会引起问题。有没有一种方法可以创建一个包含字符串值的数据框架? - Faheem Mitha
data.frame 调用中添加 stringsAsFactors=FALSE。如果调用是隐式的(如最后一个示例),则必须使其显式:data.frame(c("[]", "[]"), stringsAsFactors=FALSE) - Brian Diggs
还有一个全局选项stringsAsFactors,它也可以控制这个问题。我将其保留为默认设置,并根据需要进行更改以实现可重复性。 - Brian Diggs
我得到了$ c("[]", "[]") : chr "[]" "[]"而不是$ c("[]", "[]") : Factor w/ 1 level "[]": 1 1. 我正在使用R 1.15.1。有什么想法为什么会有这种差异? - Faheem Mitha
getOption("stringsAsFactors") 会返回什么? - Brian Diggs
啊,是的,我忘记在.Rprofile中设置了options(stringsAsFactors=FALSE)。也许这不是一个好主意。 - Faheem Mitha

15

使用 data.frame 代替 cbind 应该会有帮助。

x <- data.frame(col1=c(10, 20), col2=c("[]", "[]"), col3=c("[[1,2]]","[[1,3]]"))
x
  col1 col2    col3
1   10   [] [[1,2]]
2   20   [] [[1,3]]

sapply(x, class) # looking into x to see the class of each element
     col1      col2      col3 
"numeric"  "factor"  "factor" 

正如你所见,col1的元素是你想要的 numeric 类型。

data.frame 可以有不同 class 的变量: numeric, factorcharacter。但是 matrix 不行,一旦你把一个 character 元素放进矩阵里,所有其他元素都会变成这个类型,无论之前它们是什么类型。


谢谢。我能把col2col3的类转换成字符串吗? - Faheem Mitha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接