我有一个包含列group_ID和class多个数字特征的数据框,以及一些字符元数据,即:
group_ID class var1 var2 var3 metadata
a foo 1 324 3 cat
a bar 1.3 34 53 dog
a baz 31 34 5 elephant
b foo 34 34 943 dolphin
b bar 94 51 23 chipmunk
b baz 985 595 43 badger
c foo 43 93 23 tapir
c bar 43 23 23 monkey
c baz 40 53 512 duck
Run Code Online (Sandbox Code Playgroud)
我想计算foo每个类的中位数group_ID,然后将每一行除以匹配的中位数group_ID.
在这个例子中我只有1行每个foo,所以中间将是相同的初始值,但在现实中,我为每个许多行class和group_ID.
有一个简单的方法吗?我对far的最佳尝试包括为中值创建一个单独的数据帧foo,然后在一个可怕的循环中按group_ID和扫描进行拆分,但最终我失去了元数据列.这样做似乎很常见,我确信我错过了一些东西.
任何帮助,将不胜感激.
我们可以使用mutate_eachfrom dplyr除以条件.
library(dplyr)
df %>% group_by(group_ID) %>%
mutate_each(funs(./median(.[class == "foo"])), var1:var3)
# Source: local data frame [9 x 6]
# Groups: group_ID
#
# group_ID class var1 var2 var3 metadata
# 1 a foo 1.0000000 1.0000000 1.00000000 cat
# 2 a bar 1.3000000 0.1049383 17.66666667 dog
# 3 a baz 31.0000000 0.1049383 1.66666667 elephant
# 4 b foo 1.0000000 1.0000000 1.00000000 dolphin
# 5 b bar 2.7647059 1.5000000 0.02439024 chipmunk
# 6 b baz 28.9705882 17.5000000 0.04559915 badger
# 7 c foo 1.0000000 1.0000000 1.00000000 tapir
# 8 c bar 1.0000000 0.2473118 1.00000000 monkey
# 9 c baz 0.9302326 0.5698925 22.26086957 duck
Run Code Online (Sandbox Code Playgroud)
如果OP想要将这些列添加为新的/附加列并保持以前的数据不变,您可以将上述方法修改为:
df %>%
group_by(group_ID) %>%
mutate_each(funs(./median(.[class == "foo"])), setNames(var1:var3, paste0("varN", 1:3)))
Run Code Online (Sandbox Code Playgroud)
这是一个data.table解决方案.我们将'data.frame'转换为'data.table'(setDT(df)),按'group_ID'分组,我们循环(with lapply)通过以列名'var'开头的列子grep集(使用我们是子集),除每列由该列median的子集对应于'class'中的'foo'值.这可以:=作为新列分配(),或者我们可以将其分配回同一列以替换原始列.替换原始列的一个问题是我们应该将原始列与替换的列匹配class.如果'var'列的原始类是numeric,那么它将作为median计算和除法将新列转换为numeric.如果原始列是integer类,则可能的选项是将类更改为numeric然后分配.
library(data.table)
setDT(df)[, paste0("varN", 1:3) := lapply(.SD[,
grep("^var", names(.SD)), with=FALSE],
function(x) x/median(x[class=="foo"])), group_ID]
df
# group_ID class var1 var2 var3 metadata varN1 varN2 varN3
#1: a foo 1.0 324 3 cat 1.0000000 1.0000000 1.00000000
#2: a bar 1.3 34 53 dog 1.3000000 0.1049383 17.66666667
#3: a baz 31.0 34 5 elephant 31.0000000 0.1049383 1.66666667
#4: b foo 34.0 34 943 dolphin 1.0000000 1.0000000 1.00000000
#5: b bar 94.0 51 23 chipmunk 2.7647059 1.5000000 0.02439024
#6: b baz 985.0 595 43 badger 28.9705882 17.5000000 0.04559915
#7: c foo 43.0 93 23 tapir 1.0000000 1.0000000 1.00000000
#8: c bar 43.0 23 23 monkey 1.0000000 0.2473118 1.00000000
#9: c baz 40.0 53 512 duck 0.9302326 0.5698925 22.26086957
Run Code Online (Sandbox Code Playgroud)