我经常遇到的一般问题:我想对data.frame执行一些操作,对于每个因子级别将生成一个数字,为此它使用来自多个列的信息。如何在R?
中写出来我考虑过这些功能:
data.frame
作为结果,我知道我可以转换它但它很难看,我更喜欢另一种解决方案! 答案 0 :(得分:2)
OP要求一般答案,所以我认为'plyr'包是最合适的。 'plyr'软件包在接近大型数据集时有局限性,但对于日常使用(隐含在原帖中),'plyr'函数对于任何R用户来说都是很好的资产。
设置:以下是供我们使用的快速数据示例。
data <- data.frame(id=1:50, group=sample(letters[1:3], 50, rep=TRUE), x_Value=sample(1:500, 50), y_Value=sample(2:5, 50, rep=TRUE)*100)
如何使用plyr :我只是将这里的基本用途作为例子来解决问题。首先,加载包。
library(plyr)
现在,让我们开始计算事物。使用'plyr'功能,您可以根据输入和输出选择函数的前两个字母。在这个例子中,我将输入一个数据帧(d)并输出一个数据帧(d),所以我将使用'ddply'函数。
'ddply'函数使用以下语法:
ddply(
data_source,
.(grouping_variables),
function,
column_definitions)
首先,让我们快速找出有多少条目属于组a,b和c:
ddply(
data,
.(group),
summarize,
N=length(id))
# group N
# 1 a 17
# 2 b 16
# 3 c 17
在这里,我们首先指定数据源,然后指定我们想要通过'group'变量对行进行分组。我们使用'summarize'函数来删除除grouping_variables和column_definitions之外的所有列。使用'length'函数基本上只是为了这个目的。
现在,让我们在数据中添加一列,显示组对x和y值的含义。
ddply(
data,
.(group),
mutate,
group_mean_x=mean(x_Value),
group_mean_y=mean(y_Value))
# id group x_Value y_Value group_mean_x group_mean_y
# 1 8 a 301 300 218.7059 394.1176
# 2 13 a 38 500 218.7059 394.1176
# 3 14 a 425 300 218.7059 394.1176
# .....................................................
# 17 47 a 191 300 218.7059 394.1176
# 18 5 b 411 500 235.1875 325.0000
# 19 6 b 121 400 235.1875 325.0000
# 20 11 b 151 200 235.1875 325.0000
# .....................................................
# 33 49 b 354 200 235.1875 325.0000
# 34 1 c 482 400 246.1765 400.0000
# 35 2 c 43 300 246.1765 400.0000
# .....................................................
# 50 50 c 248 500 246.1765 400.0000
我已将结果截断以缩短结果。在这里,我们使用相同的数据源和分组变量,但'mutate'函数在添加列时保留数据源中的所有数据。
现在,让我们用以前的数据做两步。让我们在汇总表中显示x和y均值之间的均值和差异。
ddply(
data,
.(group),
summarize,
group_mean_x=mean(x_Value),
group_mean_y=mean(y_Value),
difference=group_mean_x - group_mean_y)
# group group_mean_x group_mean_y difference
# 1 a 218.7059 394.1176 -175.4118
# 2 b 235.1875 325.0000 -89.8125
# 3 c 246.1765 400.0000 -153.8235
我向您展示了这个例子,因为有一些重要的事情......我们正在使用我们刚刚定义的列作为不同列定义的一部分。这在创建汇总表时非常有用。
最后,让我们按两个因素分组:x值的10 ^ 2位置的组和数字。让我们创建一个汇总表,显示每个组的平均x和y值以及10 ^ 2位x值。
ddply(
data,
.(group, x_100=as.integer(x_Value/100)),
summarize,
mean_x=mean(x_Value),
mean_y=mean(y_Value))
# group x_100 mean_x mean_y
# 1 a 0 20.0000 425.0000
# 2 a 1 145.6667 333.3333
# 3 a 2 272.0000 400.0000
# 4 a 3 328.6667 433.3333
# 5 a 4 427.5000 350.0000
# 6 b 0 37.0000 200.0000
# 7 b 1 148.6667 383.3333
# 8 b 2 230.0000 325.0000
# 9 b 3 363.0000 200.0000
# 10 b 4 412.5000 400.0000
# 11 c 0 55.6000 360.0000
# 12 c 1 173.5000 350.0000
# 13 c 2 262.5000 450.0000
# 14 c 3 355.6667 400.0000
# 15 c 4 481.0000 433.3333
这个例子很重要,因为它向我们展示了两件事:我们可以使用向量化语句创建分组列,我们可以通过用逗号分隔列列表来分组多个列。
这一组快速示例应足以开始使用'plyr'软件包。有关详细信息,请参阅help(plyr)
。
答案 1 :(得分:1)
答案 2 :(得分:1)
基础R解决方案是使用lapply
和split
:
> data.frame(lapply(split(iris[,1:4], iris[,5]), colMeans))
setosa versicolor virginica
Sepal.Length 5.006 5.936 6.588
Sepal.Width 3.428 2.770 2.974
Petal.Length 1.462 4.260 5.552
Petal.Width 0.246 1.326 2.026
...或者您可以将其包装在do.call(rbind, ...)
中,以便以稍微不同的形式获得输出:
> data.frame(do.call(rbind,lapply(split(iris[,1:4], iris[,5]), colMeans)))
Sepal.Length Sepal.Width Petal.Length Petal.Width
setosa 5.006 3.428 1.462 0.246
versicolor 5.936 2.770 4.260 1.326
virginica 6.588 2.974 5.552 2.026
...如果您的数据可以存储在矩阵中,请使用sapply
:
> sapply(split(iris[,1:4], iris[,5]), colMeans)
setosa versicolor virginica
Sepal.Length 5.006 5.936 6.588
Sepal.Width 3.428 2.770 2.974
Petal.Length 1.462 4.260 5.552
Petal.Width 0.246 1.326 2.026
答案 3 :(得分:1)
搜索SO会产生很多答案,这是一个简单的例子。
library(data.table)
dt = data.table(a = c(1:6), b = c(1,1,1,2,2,2), c = c(1,2,1,2,1,2))
dt
# a b c
#1: 1 1 1
#2: 2 1 2
#3: 3 1 1
#4: 4 2 2
#5: 5 2 1
#6: 6 2 2
dt[, sum(a), by = list(b, c)]
# b c V1
#1: 1 1 4
#2: 1 2 2
#3: 2 2 10
#4: 2 1 5
即使在这个简单的例子中,人们也可以看到plyr
ddply
的优势 - 更简单(更人性化和更短)的语法,保持分组顺序,当然还有更快的速度。 (供参考,plyr
版本为ddply(dt, .(b, c), summarize, sum(a))
)