一周前,我本可以手动完成此操作:按组分组数据到新数据帧。对于每个数据帧计算意味着每个变量,然后是rbind。非常笨重...
现在我已经了解了split
和plyr
,我想必须有一种更简单的方法来使用这些工具。请不要证明我错了。
test_data <- data.frame(cbind(
var0 = rnorm(100),
var1 = rnorm(100,1),
var2 = rnorm(100,2),
var3 = rnorm(100,3),
var4 = rnorm(100,4),
group = sample(letters[1:10],100,replace=T),
year = sample(c(2007,2009),100, replace=T)))
test_data$var1 <- as.numeric(as.character(test_data$var1))
test_data$var2 <- as.numeric(as.character(test_data$var2))
test_data$var3 <- as.numeric(as.character(test_data$var3))
test_data$var4 <- as.numeric(as.character(test_data$var4))
我正在和ddply
两个玩弄,但是我无法生产出我想要的东西 - 即每个群体都有这样的表格
group a |2007|2009|
________|____|____|
var1 | xx | xx |
var2 | xx | xx |
etc. | etc| ect|
也许d_ply
和一些odfweave
输出会起作用。非常感谢投入。
P.S。我注意到data.frame将rnorm转换为data.frame中的因子?我怎么能避免这种情况 - 我(rnorm(100)不起作用所以我必须像上面那样转换为数字
答案 0 :(得分:11)
您可以使用by()
执行此操作。首先设置一些数据:
R> set.seed(42)
R> testdf <- data.frame(var1=rnorm(100), var2=rnorm(100,2), var3=rnorm(100,3),
group=as.factor(sample(letters[1:10],100,replace=T)),
year=as.factor(sample(c(2007,2009),100,replace=T)))
R> summary(testdf)
var1 var2 var3 group year
Min. :-2.9931 Min. :-0.0247 Min. :0.30 e :15 2007:50
1st Qu.:-0.6167 1st Qu.: 1.4085 1st Qu.:2.29 c :14 2009:50
Median : 0.0898 Median : 1.9307 Median :2.98 f :12
Mean : 0.0325 Mean : 1.9125 Mean :2.99 h :12
3rd Qu.: 0.6616 3rd Qu.: 2.4618 3rd Qu.:3.65 d :11
Max. : 2.2866 Max. : 4.7019 Max. :5.46 b :10
(Other):26
使用by()
:
R> by(testdf[,1:3], testdf$year, mean)
testdf$year: 2007
var1 var2 var3
0.04681 1.77638 3.00122
---------------------------------------------------------------------
testdf$year: 2009
var1 var2 var3
0.01822 2.04865 2.97805
R> by(testdf[,1:3], list(testdf$group, testdf$year), mean)
## longer answer by group and year suppressed
你仍然需要为你的桌子重新格式化它,但它确实在一行中给你答案的要点。
编辑:可以通过
进行进一步处理R> foo <- by(testdf[,1:3], list(testdf$group, testdf$year), mean)
R> do.call(rbind, foo)
var1 var2 var3
[1,] 0.62352 0.2549 3.157
[2,] 0.08867 1.8313 3.607
[3,] -0.69093 2.5431 3.094
[4,] 0.02792 2.8068 3.181
[5,] -0.26423 1.3269 2.781
[6,] 0.07119 1.9453 3.284
[7,] -0.10438 2.1181 3.783
[8,] 0.21147 1.6345 2.470
[9,] 1.17986 1.6518 2.362
[10,] -0.42708 1.5683 3.144
[11,] -0.82681 1.9528 2.740
[12,] -0.27191 1.8333 3.090
[13,] 0.15854 2.2830 2.949
[14,] 0.16438 2.2455 3.100
[15,] 0.07489 2.1798 2.451
[16,] -0.03479 1.6800 3.099
[17,] 0.48082 1.8883 2.569
[18,] 0.32381 2.4015 3.332
[19,] -0.47319 1.5016 2.903
[20,] 0.11743 2.2645 3.452
R> do.call(rbind, dimnames(foo))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
[2,] "2007" "2009" "2007" "2009" "2007" "2009" "2007" "2009" "2007" "2009"
您可以更多地使用dimnames
:
R> expand.grid(dimnames(foo))
Var1 Var2
1 a 2007
2 b 2007
3 c 2007
4 d 2007
5 e 2007
6 f 2007
7 g 2007
8 h 2007
9 i 2007
10 j 2007
11 a 2009
12 b 2009
13 c 2009
14 d 2009
15 e 2009
16 f 2009
17 g 2009
18 h 2009
19 i 2009
20 j 2009
R>
编辑:通过这种方式,我们可以为结果创建data.frame
,而无需仅使用基础R来使用外部包:
R> data.frame(cbind(expand.grid(dimnames(foo)), do.call(rbind, foo)))
Var1 Var2 var1 var2 var3
1 a 2007 0.62352 0.2549 3.157
2 b 2007 0.08867 1.8313 3.607
3 c 2007 -0.69093 2.5431 3.094
4 d 2007 0.02792 2.8068 3.181
5 e 2007 -0.26423 1.3269 2.781
6 f 2007 0.07119 1.9453 3.284
7 g 2007 -0.10438 2.1181 3.783
8 h 2007 0.21147 1.6345 2.470
9 i 2007 1.17986 1.6518 2.362
10 j 2007 -0.42708 1.5683 3.144
11 a 2009 -0.82681 1.9528 2.740
12 b 2009 -0.27191 1.8333 3.090
13 c 2009 0.15854 2.2830 2.949
14 d 2009 0.16438 2.2455 3.100
15 e 2009 0.07489 2.1798 2.451
16 f 2009 -0.03479 1.6800 3.099
17 g 2009 0.48082 1.8883 2.569
18 h 2009 0.32381 2.4015 3.332
19 i 2009 -0.47319 1.5016 2.903
20 j 2009 0.11743 2.2645 3.452
R>
答案 1 :(得分:11)
根据您想要的结果格式,重塑包将比plyr更有效。
test_data <- data.frame(
var0 = rnorm(100),
var1 = rnorm(100,1),
var2 = rnorm(100,2),
var3 = rnorm(100,3),
var4 = rnorm(100,4),
group = sample(letters[1:10],100,replace=T),
year = sample(c(2007,2009),100, replace=T))
library(reshape)
Molten <- melt(test_data, id.vars = c("group", "year"))
cast(group + variable ~ year, data = Molten, fun = mean)
结果如下所示
group variable 2007 2009
1 a var0 0.003767891 0.340989068
2 a var1 2.009026385 1.162786943
3 a var2 1.861061882 2.676524736
4 a var3 2.998011426 3.311250399
5 a var4 3.979255971 4.165715967
6 b var0 -0.112883844 -0.179762343
7 b var1 1.342447279 1.199554144
8 b var2 2.486088196 1.767431740
9 b var3 3.261451449 2.934903824
10 b var4 3.489147597 3.076779626
11 c var0 0.493591055 -0.113469315
12 c var1 0.157424796 -0.186590644
13 c var2 2.366594176 2.458204041
14 c var3 3.485808031 2.817153628
15 c var4 3.681576886 3.057915666
16 d var0 0.360188789 1.205875725
17 d var1 1.271541181 0.898973536
18 d var2 1.824468264 1.944708165
19 d var3 2.323315162 3.550719308
20 d var4 3.852223640 4.647498956
21 e var0 -0.556751465 0.273865769
22 e var1 1.173899189 0.719520372
23 e var2 1.935402724 2.046313047
24 e var3 3.318669590 2.871462470
25 e var4 4.374478734 4.522511874
26 f var0 -0.258956555 -0.007729091
27 f var1 1.424479454 1.175242755
28 f var2 1.797948551 2.411030282
29 f var3 3.083169793 3.324584667
30 f var4 4.160641429 3.546527820
31 g var0 0.189038036 -0.683028110
32 g var1 0.429915866 0.827761101
33 g var2 1.839982321 1.513104866
34 g var3 3.106414330 2.755975622
35 g var4 4.599340239 3.691478466
36 h var0 0.015557352 -0.707257185
37 h var1 0.933199148 1.037655156
38 h var2 1.927442457 2.521369108
39 h var3 3.246734239 3.703213646
40 h var4 4.242387776 4.407960355
41 i var0 0.885226638 -0.288221276
42 i var1 1.216012653 1.502514588
43 i var2 2.302815441 1.905731471
44 i var3 2.026631277 2.836508446
45 i var4 4.800676814 4.772964668
46 j var0 -0.435661855 0.192703997
47 j var1 0.836814185 0.394505861
48 j var2 1.663523873 2.377640369
49 j var3 3.489536343 3.457597835
50 j var4 4.146020948 4.281599816
答案 2 :(得分:8)
编辑:我写了以下内容然后意识到蒂埃里已经写了几乎完全相同的答案。我莫名其妙地忽略了他的回答。所以,如果你喜欢这个答案,请投反对票。因为我花时间打字,所以我要继续发布。
这种东西消耗的时间比我希望的多得多!这是使用Hadley Wickham的reshape package的解决方案。此示例不会完全您所询问的内容,因为结果全部在一个大表中,而不是每个组的表。
您使用数值显示为因素的麻烦是因为您使用了cbind并且所有内容都被撞入了类型字符的矩阵中。很酷的是你不需要带有data.frame的cbind。
test_data <- data.frame(
var0 = rnorm(100),
var1 = rnorm(100,1),
var2 = rnorm(100,2),
var3 = rnorm(100,3),
var4 = rnorm(100,4),
group = sample(letters[1:10],100,replace=T),
year = sample(c(2007,2009),100, replace=T))
library(reshape)
molten_data <- melt(test_data, id=c("group", "year")))
cast(molten_data, group + variable ~ year, mean)
,结果如下:
group variable 2007 2009
1 a var0 -0.92040686 -0.154746420
2 a var1 1.06603832 0.559765035
3 a var2 2.34476321 2.206521587
4 a var3 3.01652065 3.256580166
5 a var4 3.75256699 3.907777127
6 b var0 -0.53207427 -0.149144766
7 b var1 0.75677714 0.879387608
8 b var2 2.41739521 1.224854891
9 b var3 2.63877431 2.436837719
10 b var4 3.69640598 4.439047363
...
我写了blog post recently关于做与plyr类似的事情。我应该做一个关于如何使用reshape包做同样事情的第2部分。 plyr和reshape都是由Hadley Wickham编写的,是疯狂有用的工具。
答案 3 :(得分:5)
首先,你不需要使用cbind,这就是为什么一切都是一个因素。这有效:
test_data <- data.frame(
var0 = rnorm(100),
var1 = rnorm(100,1),
var2 = rnorm(100,2),
var3 = rnorm(100,3),
var4 = rnorm(100,4),
group = sample(letters[1:10],100,replace=T),
year = sample(c(2007,2009),100, replace=T))
其次,最佳做法是使用“。”而不是变量名中的“_”。 See the google style guide(例如)。
最后,您可以使用Rigroup包;它非常快。将igroupMeans()函数与apply结合使用,并设置索引i=as.factor(paste(test_data$group,test_data$year,sep=""))
。我稍后会尝试包含一个这样的例子。
编辑6/9/2017
从CRAN中删除了Rigroup包。见this
答案 4 :(得分:5)
可以使用基本的R函数来完成:
n <- 100
test_data <- data.frame(
var0 = rnorm(n),
var1 = rnorm(n,1),
var2 = rnorm(n,2),
var3 = rnorm(n,3),
var4 = rnorm(n,4),
group = sample(letters[1:10],n,replace=TRUE),
year = sample(c(2007,2009),n, replace=TRUE)
)
tapply(
seq_len(nrow(test_data)),
test_data$group,
function(ind) sapply(
c("var0","var1","var2","var3","var4"),
function(x_name) tapply(
test_data[[x_name]][ind],
test_data$year[ind],
mean
)
)
)
说明:
在R 2.9.2中,结果是:
$a
var0.2007 var1.2007 var2.2007 var3.2007 var4.2007
-0.3123034 0.8759787 1.9832617 2.7063034 4.1322758
$b
var0 var1 var2 var3 var4
2007 0.81366885 0.4189896 2.331256 3.073276 4.164639
2009 -0.08916257 1.5442126 3.008014 3.215019 4.398279
$c
var0 var1 var2 var3 var4
2007 0.4232098 1.3657369 1.386627 2.808511 3.878809
2009 0.3245751 0.6672073 1.797886 1.752568 3.632318
$d
var0 var1 var2 var3 var4
2007 -0.1335138 0.5925237 2.303543 3.293281 3.234386
2009 0.9547751 2.2111581 2.678878 2.845234 3.300512
$e
var0 var1 var2 var3 var4
2007 -0.5958653 1.3535658 1.886918 3.036121 4.120889
2009 0.1372080 0.7215648 2.298064 3.186617 3.551147
$f
var0 var1 var2 var3 var4
2007 -0.3401813 0.7883120 1.949329 2.811438 4.194481
2009 0.3012627 0.2702647 3.332480 3.480494 2.963951
$g
var0 var1 var2 var3 var4
2007 1.225245 -0.3289711 0.7599302 2.903581 4.200023
2009 0.273858 0.2445733 1.7690299 2.620026 4.182050
$h
var0 var1 var2 var3 var4
2007 -1.0126650 1.554403 2.220979 3.713874 3.924151
2009 -0.6187407 1.504297 1.321930 2.796882 4.179695
$i
var0 var1 var2 var3 var4
2007 0.01697314 1.318965 1.794635 2.709925 2.899440
2009 -0.75790995 1.033483 2.363052 2.422679 3.863526
$j
var0 var1 var2 var3 var4
2007 -0.7440600 1.6466291 2.020379 3.242770 3.727347
2009 -0.2842126 0.5450029 1.669964 2.747455 4.179531
根据我的随机数据,“a”组存在问题 - 仅存在2007个案例。如果年份将是因素(2007和2009年水平),那么结果可能看起来更好(每年你会有两行,但可能有NA)。
结果是列表,因此您可以使用lapply来例如。转换为乳胶表,html表,打印屏幕转置等
答案 5 :(得分:3)
首先做一个简单的聚合来总结它。
df <- aggregate(cbind(var0, var1, var2, var3, var4) ~ year + group, test_data, mean)
这使得像这样的data.frame ......
year group var0 var1 var2 var3 var4
1 2007 a 42.25000 0.2031277 2.145394 2.801812 3.571999
2 2009 a 30.50000 1.2033653 1.475158 3.618023 4.127601
3 2007 b 52.60000 1.4564604 2.224850 3.053322 4.339109
...
这本身就非常接近你想要的。你现在可以按小组分手。
l <- split(df, df$group)
好的,所以不是这样,但如果你真的想要我们可以改进输出。
lapply(l, function(x) {d <- t(x[,3:7]); colnames(d) <- x[,2]; d})
$a
2007 2009
var0 42.2500000 30.500000
var1 0.2031277 1.203365
var2 2.1453939 1.475158
...
这没有你所有的表格格式,但它的组织与你描述的完全一致,并且非常接近。最后一步,你可以很喜欢你喜欢的方式。
这是唯一符合所请求组织的答案,这是在R. BTW中最快的方式。我不打算做最后一步,只是坚持聚合的第一个输出。或者可能是分裂。