我正在尝试将向量“均值”合并到数据帧。 我的数据框看起来像这样Data = growth
我首先使用以下命令计算了不同组(一组=人口+温度+大小+复制品)的所有均值:
means<-aggregate(TL ~ Population + Temperature + Replicat + Size + Measurement, data=growth, list=growth$Name, mean)
然后,我选择测量1的方法如下,因为我只对这些方法感兴趣。
meansT0<-means[which(means$Measurement=="1"),]
现在,我想将此均值向量合并到我的数据帧(=增长)中,以便每个组的正确均值对应于数据帧的右侧。
然后,目标是根据数据帧的所属组(以及测量1以外的所有其他测量),将每组的平均值(在度量1中)乘以数据框的每个元素。也许不需要在数据框中添加均值列?您知道执行此操作的任何命令吗?
[27.06.18] 我组成了这个简化的数据框,希望对您有所帮助。 因此,我要对数据框中的每个个体和每个度量(这里只有Measurement 1和Measurement 2,通常我有更多)进行细分,以其所属组的平均值为MEASUREMENT1。
因此,如果我按组( 1组 =人口+温度+测量)获得平均值:
means<-aggregate(TL ~ Population + Temperature + Measurement, data=growth, list=growth$Name, mean)
means
我得到了均值的这些值(在此示例中):
Population Temperature Measurement TL
JUB 15 **1** **12.00000**
JUB 20 **1** **15.66667**
JUB 15 2 17.66667
JUB 20 2 18.66667
JUB 15 3 23.66667
JUB 20 3 24.33333
我们只对测量1中的方法感兴趣。对于数据框中的每个人,我想在测量1中将其所属组的平均值相乘(在此示例中,请参见使用R命令的数据框): -对于组JUB + 15 +测量1 ,平均值= 12 -对于组JUB + 20 + Measurement 1 ,平均值= 15.66
growth<-data.frame(Population=c("JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB","JUB", "JUB", "JUB"), Measurement=c("1","1","1","1","1","1","2","2","2","2","2","2", "3", "3", "3", "3", "3", "3"),Temperature=c("15","15","15","20", "20", "20","15","15","15","20", "20", "20","15","15","15","20", "20", "20"),TL=c(11,12,13,15,18,14, 16,17,20,21,19,16, 25,22,24,26,24,23), New_TL=c("11-12", "12-12", "13-12", "15-15.66", "18-15.66", "14-15.66", "16-12", "17-12", "20-12", "21-15.66", "19-15.66", "16-15.66", "25-12", "22-12", "24-12", "26-15.66", "24-15.66", "23-15.66"))
print(growth)
我希望借此,您可以更好地了解我正在尝试做的事情。我有很多数据,如果必须手动执行此操作,这将花费我很多时间,并增加了我犯错误的风险。
答案 0 :(得分:1)
这里是tidyverse
的一个选项。按分组列分组后,使用mutate_at
指定感兴趣的列,并获得该列(.
)与它的mean
之间的差。
library(tidyverse)
growth %>%
group_by(Population, Temperature, Replicat, Size, Measurement) %>%
mutate_at(vars(HL, TL), funs(MeanGroupDiff = .
- mean(.[Measurement == 1])))
使用带有mtcars
数据集的可重现示例
data(mtcars)
mtcars %>%
group_by(cyl, vs) %>%
mutate_at(vars(mpg, disp), funs(MeanGroupDiff = .- mean(.[am==1])))
答案 1 :(得分:0)
您是否考虑过使用data.table
软件包?非常适合执行您描述的这类分组,过滤,联接和聚合操作,从长远来看可以节省大量时间。
下面的代码显示了使用mtcars
看起来与您描述的工作流相似但基于内置data.table
数据集的工作流的样子。
需要明确的是,还有一些方法可以使用基础R
以及dplyr
之类的其他软件包来完成您描述的操作,只是根据我发现的内容提出建议对我的个人工作最有用。
library(data.table)
## Convert mtcars to a data.table
## only include columns `mpg`, `cyl`, `am` and `gear` for brevity
DT <- as.data.table(mtcars)[, .(mpg, cyl,am, gear)]
## Take a subset where `cyl` is equal to 6
DT <- DT[cyl == 6]
## Calculate grouped mean based on `gear` and `am` as grouping variables
DT[,group_mpg_avg := mean(mpg), keyby = .(gear, am)]
## Calculate each row's difference from the group mean
DT[,mpg_diff_from_group := mpg - group_mpg_avg]
print(DT)
# mpg cyl am gear group_mpg_avg mpg_diff_from_group
# 1: 21.4 6 0 3 19.75 1.65
# 2: 18.1 6 0 3 19.75 -1.65
# 3: 19.2 6 0 4 18.50 0.70
# 4: 17.8 6 0 4 18.50 -0.70
# 5: 21.0 6 1 4 21.00 0.00
# 6: 21.0 6 1 4 21.00 0.00
# 7: 19.7 6 1 5 19.70 0.00
答案 2 :(得分:0)
考虑by
来按因素对数据框进行子集化(但为了比较组1和所有其他组,请省略 Measurement )。然后,对所需的列运行ifelse
条件逻辑计算。由于by
将返回数据帧列表,因此请用do.call()
将所有外部绑定:
df_list <- by(growth, growth[,c("Population", "Temperature")], function(sub) {
# TL CORRECTION
sub$Correct_TL <- ifelse(sub$Measurement != 1,
sub$TL - mean(subset(sub, Measurement == 1)$TL),
sub$TL)
# ADD OTHER CORRECTIONS
return(sub)
})
final_df <- do.call(rbind, df_list)
输出 (使用发布的数据)
final_df
# Population Measurement Temperature TL New_TL Correct_TL
# 1 JUB 1 15 11 11-12 11.0000000
# 2 JUB 1 15 12 12-12 12.0000000
# 3 JUB 1 15 13 13-12 13.0000000
# 7 JUB 2 15 16 16-12 4.0000000
# 8 JUB 2 15 17 17-12 5.0000000
# 9 JUB 2 15 20 20-12 8.0000000
# 13 JUB 3 15 25 25-12 13.0000000
# 14 JUB 3 15 22 22-12 10.0000000
# 15 JUB 3 15 24 24-12 12.0000000
# 4 JUB 1 20 15 15-15.66 15.0000000
# 5 JUB 1 20 18 18-15.66 18.0000000
# 6 JUB 1 20 14 14-15.66 14.0000000
# 10 JUB 2 20 21 21-15.66 5.3333333
# 11 JUB 2 20 19 19-15.66 3.3333333
# 12 JUB 2 20 16 16-15.66 0.3333333
# 16 JUB 3 20 26 26-15.66 10.3333333
# 17 JUB 3 20 24 24-15.66 8.3333333
# 18 JUB 3 20 23 23-15.66 7.3333333