按组划分列(在数据框中分组)
Dividing columns by group (Grouping in data frame)
我想通过将每个 response/column 除以其组平均值来计算相对响应值。
我已经设法产生了一个详尽的(因此不令人满意的)方法。我的数据集非常大,包含多个组和回复。
###############
# example
# used packages
require(plyr)
# sample data
group <- c(rep("alpha", 3), rep("beta", 3), rep("gamma", 3))
a <- rnorm(9, 10,1) #some random data as response
b <- rnorm(9, 10,1)
df <- data.frame(group, a, b)
# my approach
# means for each group and response
df.means <- ddply(df, "group", colwise(mean))
# clunky method
df$rel.a[df$group=="alpha"] <-
df$a[df$group=="alpha"]/df.means$a[df.means$group=="alpha"]
df$rel.a[df$group=="beta"] <-
df$a[df$group=="beta"]/df.means$a[df.means$group=="beta"]
# ... etc
df$rel.b[df$group=="gamma"] <-
df$b[df$group=="gamma"]/df.means$b[df.means$group=="gamma"]
#desired outcome (well, perhaps with no missing values)
df
###############
我已经使用 r 一段时间了,但我仍然在为琐碎的数据处理程序而苦恼。我相信我一定遗漏了一些东西,我怎样才能更好地解决这些问题?
使用 data.table
包,您可以在一行中快速轻松地完成所有事情(根本不需要创建 df.means
),只需
library(data.table)
setDT(df)[, paste0("real.", names(df)[-1]) :=
lapply(.SD, function(x) x/mean(x)),
group]
这将 运行 对 df
内的所有列(group
除外)除以 group
,并将每个值除以组均值
编辑: 如果您想覆盖原始列(如 dplyr
答案中的内容,您可以稍作修改(删除 paste0
部分):
setDT(df)[, names(df)[-1] := lapply(.SD, function(x) x/mean(x)), group]
数据帧的下一个版本 plyr 包 dplyr 很容易理解:
library(dplyr)
df %>% group_by(group) %>% mutate_each(funs(./mean(.)))
。代表每列中的数据(按组)。 mutate_each用于修改除分组变量外的每一列。您在 funs 参数中指定应将哪些函数应用于每一列。
如果我没理解错的话,你也可以在 dplyr
中轻松做到这一点。鉴于以上数据
library(dplyr)
df %>% group_by(group) %>% mutate(aresp = a/ mean(a), bresp= b/mean(b))
returns:
group a b aresp bresp
1 alpha 10.052847 8.076405 1.0132828 0.8288214
2 alpha 10.002243 11.447665 1.0081822 1.1747888
3 alpha 9.708111 9.709265 0.9785350 0.9963898
4 beta 10.732693 7.483065 0.9751125 0.8202278
5 beta 11.719656 11.270522 1.0647824 1.2353754
6 beta 10.567513 8.615878 0.9601051 0.9443968
7 gamma 10.221040 11.181763 1.0035630 0.9723315
8 gamma 10.302611 11.286443 1.0115721 0.9814341
9 gamma 10.030605 12.031643 0.9848649 1.0462344
我想通过将每个 response/column 除以其组平均值来计算相对响应值。 我已经设法产生了一个详尽的(因此不令人满意的)方法。我的数据集非常大,包含多个组和回复。
###############
# example
# used packages
require(plyr)
# sample data
group <- c(rep("alpha", 3), rep("beta", 3), rep("gamma", 3))
a <- rnorm(9, 10,1) #some random data as response
b <- rnorm(9, 10,1)
df <- data.frame(group, a, b)
# my approach
# means for each group and response
df.means <- ddply(df, "group", colwise(mean))
# clunky method
df$rel.a[df$group=="alpha"] <-
df$a[df$group=="alpha"]/df.means$a[df.means$group=="alpha"]
df$rel.a[df$group=="beta"] <-
df$a[df$group=="beta"]/df.means$a[df.means$group=="beta"]
# ... etc
df$rel.b[df$group=="gamma"] <-
df$b[df$group=="gamma"]/df.means$b[df.means$group=="gamma"]
#desired outcome (well, perhaps with no missing values)
df
###############
我已经使用 r 一段时间了,但我仍然在为琐碎的数据处理程序而苦恼。我相信我一定遗漏了一些东西,我怎样才能更好地解决这些问题?
使用 data.table
包,您可以在一行中快速轻松地完成所有事情(根本不需要创建 df.means
),只需
library(data.table)
setDT(df)[, paste0("real.", names(df)[-1]) :=
lapply(.SD, function(x) x/mean(x)),
group]
这将 运行 对 df
内的所有列(group
除外)除以 group
,并将每个值除以组均值
编辑: 如果您想覆盖原始列(如 dplyr
答案中的内容,您可以稍作修改(删除 paste0
部分):
setDT(df)[, names(df)[-1] := lapply(.SD, function(x) x/mean(x)), group]
数据帧的下一个版本 plyr 包 dplyr 很容易理解:
library(dplyr)
df %>% group_by(group) %>% mutate_each(funs(./mean(.)))
。代表每列中的数据(按组)。 mutate_each用于修改除分组变量外的每一列。您在 funs 参数中指定应将哪些函数应用于每一列。
如果我没理解错的话,你也可以在 dplyr
中轻松做到这一点。鉴于以上数据
library(dplyr)
df %>% group_by(group) %>% mutate(aresp = a/ mean(a), bresp= b/mean(b))
returns:
group a b aresp bresp
1 alpha 10.052847 8.076405 1.0132828 0.8288214
2 alpha 10.002243 11.447665 1.0081822 1.1747888
3 alpha 9.708111 9.709265 0.9785350 0.9963898
4 beta 10.732693 7.483065 0.9751125 0.8202278
5 beta 11.719656 11.270522 1.0647824 1.2353754
6 beta 10.567513 8.615878 0.9601051 0.9443968
7 gamma 10.221040 11.181763 1.0035630 0.9723315
8 gamma 10.302611 11.286443 1.0115721 0.9814341
9 gamma 10.030605 12.031643 0.9848649 1.0462344