Calculate mean difference per row and per group

▼魔方 西西 提交于 2021-02-05 08:00:32

问题


I have a data.frame with many rows and columns and I want to calculate the mean difference of each value to each of the other values within a group.
Here an example:

 ID  value 
 1    4 
 1    5 
 1    7 
 2    8 
 2    6 
 2    5 
 2    6

This is what I want to calculate:

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 

I tried using aggregate() but failed to make it work.


回答1:


A solution using crossjoin in data.table library with a defect of removing the duplicated row from the original data frame:

> 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

Since duplicated rows always have the same value_mean_diff, you can always merge them to get all the duplicated rows.

> 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

Update: Since the above method is memory intensive, you can take advantage of the fact that your value_mean_diff = (value - value_mean)^2 + variance(value), which you can prove by expanding the variance based on its definition. With this as a fact, you can calculate by the following way:

> 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

Keep in mind that the var() function in R calculate the sample variance so you need to convert it to population variance by multiplying a factor (n-1)/n.




回答2:


Here's a solution using only 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


来源:https://stackoverflow.com/questions/37227238/calculate-mean-difference-per-row-and-per-group

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!