计算每行和每组的平均差
Calculate mean difference per row and per group
我有一个包含许多行和列的 data.frame
,我想计算每个值与组内其他每个值的平均差。
这里有一个例子:
ID value
1 4
1 5
1 7
2 8
2 6
2 5
2 6
这是我要计算的:
ID value value_mean_diff
1 4 (4-5)^2 + (4-7)^2 /groupsize = 3
1 5 (5-4)^2 + (5-7)^2 / 3
1 7 (7-4)^2 + (7-5)^2 / 3
2 8 (8-6)^2 + (8-5)^2 + (8-6)^2 / 4
2 6 (6-8)^2 + (6-5)^2 + (6-6)^2 / 4
2 5 (5-8)^2 + (5-6)^2 + (5-6)^2 / 4
2 6 (6-8)^2 + (6-6)^2 + (6-5)^2 / 4
我尝试使用 aggregate() 但没能成功。
在 data.table
库中使用 crossjoin
的解决方案存在从原始数据框中删除重复行的缺陷:
> dt <- setDT(df)[,setNames(CJ(value, value), c("value", "value1")), .(ID)][,.(value_mean_diff = sum((value-value1)^2)/.N),.(ID, value)]
> dt
ID value value_mean_diff
1: 1 4 3.333333
2: 1 5 1.666667
3: 1 7 4.333333
4: 2 5 2.750000
5: 2 6 1.250000
6: 2 8 4.250000
由于重复的行始终具有相同的 value_mean_diff
,您始终可以合并它们以获得所有重复的行。
> merge(dt, df, by = c("ID", "value"))
ID value value_mean_diff
1: 1 4 3.333333
2: 1 5 1.666667
3: 1 7 4.333333
4: 2 5 2.750000
5: 2 6 1.250000
6: 2 6 1.250000
7: 2 8 4.250000
更新:
由于上述方法是内存密集型的,您可以利用以下事实:您的 value_mean_diff = (value - value_mean)^2 + variance(value),您可以通过根据其定义扩展方差来证明这一点。以此为事实,您可以通过以下方式计算:
> setDT(df)[, value_mean_diff := (value - mean(value))^2 + var(value) * (.N - 1) / .N, .(ID)]
> df
ID value value_mean_diff
1: 1 4 3.333333
2: 1 5 1.666667
3: 1 7 4.333333
4: 2 8 4.250000
5: 2 6 1.250000
6: 2 5 2.750000
7: 2 6 1.250000
请记住,R 中的 var()
函数计算样本方差,因此您需要通过乘以一个因子 (n-1)/n[=28 将其转换为总体方差=].
这是一个只使用 base R 的解决方案:
myData <- data.frame(ID=c(1,1,1,2,2,2,2), value=c(4,5,7,8,6,5,6), diff=NA)
for(i in 1:nrow(myData))
myData$diff[i] <- with(data = myData,
sum((value[i] - value[ID==ID[i]])**2)/length(value[ID==ID[i]]))
myData
ID value diff
1 1 4 3.333333
2 1 5 1.666667
3 1 7 4.333333
4 2 8 4.250000
5 2 6 1.250000
6 2 5 2.750000
7 2 6 1.250000
我有一个包含许多行和列的 data.frame
,我想计算每个值与组内其他每个值的平均差。
这里有一个例子:
ID value
1 4
1 5
1 7
2 8
2 6
2 5
2 6
这是我要计算的:
ID value value_mean_diff
1 4 (4-5)^2 + (4-7)^2 /groupsize = 3
1 5 (5-4)^2 + (5-7)^2 / 3
1 7 (7-4)^2 + (7-5)^2 / 3
2 8 (8-6)^2 + (8-5)^2 + (8-6)^2 / 4
2 6 (6-8)^2 + (6-5)^2 + (6-6)^2 / 4
2 5 (5-8)^2 + (5-6)^2 + (5-6)^2 / 4
2 6 (6-8)^2 + (6-6)^2 + (6-5)^2 / 4
我尝试使用 aggregate() 但没能成功。
在 data.table
库中使用 crossjoin
的解决方案存在从原始数据框中删除重复行的缺陷:
> dt <- setDT(df)[,setNames(CJ(value, value), c("value", "value1")), .(ID)][,.(value_mean_diff = sum((value-value1)^2)/.N),.(ID, value)]
> dt
ID value value_mean_diff
1: 1 4 3.333333
2: 1 5 1.666667
3: 1 7 4.333333
4: 2 5 2.750000
5: 2 6 1.250000
6: 2 8 4.250000
由于重复的行始终具有相同的 value_mean_diff
,您始终可以合并它们以获得所有重复的行。
> merge(dt, df, by = c("ID", "value"))
ID value value_mean_diff
1: 1 4 3.333333
2: 1 5 1.666667
3: 1 7 4.333333
4: 2 5 2.750000
5: 2 6 1.250000
6: 2 6 1.250000
7: 2 8 4.250000
更新: 由于上述方法是内存密集型的,您可以利用以下事实:您的 value_mean_diff = (value - value_mean)^2 + variance(value),您可以通过根据其定义扩展方差来证明这一点。以此为事实,您可以通过以下方式计算:
> setDT(df)[, value_mean_diff := (value - mean(value))^2 + var(value) * (.N - 1) / .N, .(ID)]
> df
ID value value_mean_diff
1: 1 4 3.333333
2: 1 5 1.666667
3: 1 7 4.333333
4: 2 8 4.250000
5: 2 6 1.250000
6: 2 5 2.750000
7: 2 6 1.250000
请记住,R 中的 var()
函数计算样本方差,因此您需要通过乘以一个因子 (n-1)/n[=28 将其转换为总体方差=].
这是一个只使用 base R 的解决方案:
myData <- data.frame(ID=c(1,1,1,2,2,2,2), value=c(4,5,7,8,6,5,6), diff=NA)
for(i in 1:nrow(myData))
myData$diff[i] <- with(data = myData,
sum((value[i] - value[ID==ID[i]])**2)/length(value[ID==ID[i]]))
myData
ID value diff
1 1 4 3.333333
2 1 5 1.666667
3 1 7 4.333333
4 2 8 4.250000
5 2 6 1.250000
6 2 5 2.750000
7 2 6 1.250000