我有一个包含两列的数据框:一列是字符串,另一列是整数。
> rnames = sapply(1:20, FUN=function(x) paste("item", x, sep="."))
> x <- sample(c(1:5), 20, replace = TRUE)
> df <- data.frame(x, rnames)
> df
x rnames
1 5 item.1
2 3 item.2
3 5 item.3
4 3 item.4
5 1 item.5
6 3 item.6
7 4 item.7
8 5 item.8
9 4 item.9
10 5 item.10
11 5 item.11
12 2 item.12
13 2 item.13
14 1 item.14
15 3 item.15
16 4 item.16
17 5 item.17
18 4 item.18
19 1 item.19
20 1 item.20
我正在尝试使用'c'或'list'函数将字符串聚合到字符串或字符串(字符)的向量中,但会得到奇怪的结果:
> aggregate(rnames ~ x, df, c)
x rnames
1 1 16, 6, 11, 13
2 2 4, 5
3 3 12, 15, 17, 7
4 4 18, 20, 8, 10
5 5 1, 14, 19, 2, 3, 9
当我使用'paste'而不是'c'时,我可以看到聚合工作正常 - 但结果并不是我想要的。
> aggregate(rnames ~ x, df, paste)
x rnames
1 1 item.5, item.14, item.19, item.20
2 2 item.12, item.13
3 3 item.2, item.4, item.6, item.15
4 4 item.7, item.9, item.16, item.18
5 5 item.1, item.3, item.8, item.10, item.11, item.17
我正在寻找的是每个聚合组都将呈现为向量或点亮(因此使用c),而不是我使用'paste'获得的单个字符串。以下内容(实际上不起作用):
> aggregate(rnames ~ x, df, c)
x rnames
1 1 item.5, item.14, item.19, item.20
2 2 item.12, item.13
3 3 item.2, item.4, item.6, item.15
4 4 item.7, item.9, item.16, item.18
5 5 item.1, item.3, item.8, item.10, item.11, item.17
任何帮助将不胜感激。
答案 0 :(得分:5)
你陷入了data.frame
的常见陷阱:你的角色列不是一个字符列,它是一个因子列!因此数字而不是结果中的字符:
> rnames = sapply(1:20, FUN=function(x) paste("item", x, sep="."))
> x <- sample(c(1:5), 20, replace = TRUE)
> df <- data.frame(x, rnames)
> str(df)
'data.frame': 20 obs. of 2 variables:
$ x : int 2 5 5 5 5 4 3 3 2 4 ...
$ rnames: Factor w/ 20 levels "item.1","item.10",..: 1 12 14 15 16 17 18 19 20 2 ...
要阻止转化为因素,请在致电stringAsFactors=FALSE
时使用参数data.frame
:
> df <- data.frame(x, rnames,stringsAsFactors=FALSE)
> str(df)
'data.frame': 20 obs. of 2 variables:
$ x : int 5 5 3 5 5 3 2 5 1 5 ...
$ rnames: chr "item.1" "item.2" "item.3" "item.4" ...
> aggregate(rnames ~ x, df, c)
x rnames
1 1 item.9, item.13, item.17
2 2 item.7
3 3 item.3, item.6, item.19
4 4 item.12, item.15, item.16
5 5 item.1, item.2, item.4, item.5, item.8, item.10, item.11, item.14, item.18, item.20
避免转换为因子的另一个解决方案是函数I
:
> df <- data.frame(x, I(rnames))
> str(df)
'data.frame': 20 obs. of 2 variables:
$ x : int 3 5 4 5 4 5 3 3 1 1 ...
$ rnames:Class 'AsIs' chr [1:20] "item.1" "item.2" "item.3" "item.4" ...
摘录自?I
:
在函数data.frame中。通过将对象封装在I()中来保护对象 对data.frame的调用禁止将字符向量转换为 因素和名称的删除,并确保矩阵 作为单列插入。我也可以用来保护物体 它们将被添加到数据帧或转换为数据帧 通过as.data.frame。
它通过将类“AsIs”预先添加到对象来实现这一点 类。 “AsIs”类有一些自己的方法,包括[, as.data.frame,print和format。
答案 1 :(得分:2)
我不确定你正在寻找的是什么......所以也许一些参考输出会让我们知道我们的目标是什么?
但是,由于你的最后一段代码似乎与你所追求的很接近,所以可能会有以下解决方案:
> library(plyr)
> ddply(df, .(x), summarize, rnames = paste(rnames, collapse = "|"))
x rnames
1 1 item.9|item.11|item.20
2 2 item.1|item.2|item.15|item.16
3 3 item.7|item.8
4 4 item.4|item.5|item.6|item.12|item.13
5 5 item.3|item.10|item.14|item.17|item.18|item.19
您可以通过将collapse参数更改为paste()来改变单个元素粘在一起的方式。
或者,如果您想将每个组作为一个vetor,那么您可以使用它:
> df$rnames = as.character(df$rnames)
> L = dlply(df, .(x), function(df) {df$rnames})
> L
$`1`
[1] "item.9" "item.11" "item.20"
$`2`
[1] "item.1" "item.2" "item.15" "item.16"
$`3`
[1] "item.7" "item.8"
$`4`
[1] "item.4" "item.5" "item.6" "item.12" "item.13"
$`5`
[1] "item.3" "item.10" "item.14" "item.17" "item.18" "item.19"
attr(,"split_type")
[1] "data.frame"
attr(,"split_labels")
x
1 1
2 2
3 3
4 4
5 5
这为您提供了一个向量列表,这就是您所追求的。每个组都可以从结果列表中编入索引:
> L[[1]]
[1] "item.9" "item.11" "item.20"