【问题标题】:Joining data with weighted averages and multiple weights in R在 R 中使用加权平均值和多个权重连接数据
【发布时间】:2018-03-02 17:44:14
【问题描述】:

所以我有this question,但范围变得更大/更复杂。

基本上,我想组合两个表并计算任何重复 ID 的加权平均值。问题是我将有多组需要使用不同权重的列。这是我的两个数据集(RMS1 和 RMS2)和期望的结果(已加入):

RMS1:
id,freq1,sev1,count1,freq2,sev2,count2
111 0    2    50     1     2    25
222 1    3    75     2     4    50

RMS2:               
id,freq1,sev1,count1,freq2,sev2,count2
222 2    4    25     6     6    200
333 4    5    60     3     2    20

Joined:                         
id  freq1   sev1    freq2   sev2        
111 0       2       1       2       
222 1.25*   3.25*   5**     5.5**       
333 4       5       3       2

所以 * 值是基于 count1 的加权平均值,但 ** 值是基于 count2 的加权平均值(至少它们应该是,我试图快速进行数学计算)。我的整个数据集有 13 个组,它们使用单​​独的权重计数。我有这段代码,但显然它需要扩展以接受多个权重:

Joined <- bind_rows(RMS1, RMS2) %>%
  group_by(id) %>%
  summarise_at(vars(-count1), funs(weighted.mean(., count1))) %>%
  as.data.frame()

作为 R 的新手,我什至不知道从哪里开始。我找到了possibly related question,但它超出了我的想象。提前致谢。

【问题讨论】:

  • 当你说你有 13 个组时,你是什么意思?你的意思是有count3、count4等等……还是说有RMS3、RMS4等等……或者说有id 333、444、555等等……
  • 我的意思是有频率 1-13、sev1-13 和计数 1-13

标签: r weighted-average


【解决方案1】:

使用 的解决方案。思路是对数据框进行转换,进行计算,再转换回原来的格式。

library(dplyr)
library(tidyr)

Joined <- bind_rows(RMS1, RMS2) %>%
  mutate(rowid = 1:n()) %>%
  gather(Column, Value, -id, -rowid) %>%
  extract(Column, into = c("Type", "Number"), 
          regex = "([A-Za-z]*)([0-9]*)", convert = TRUE) %>%
  spread(Type, Value) %>%
  group_by(id, Number) %>%
  summarise_at(vars(-rowid, -count), funs(weighted.mean(., count))) %>%
  gather(Type, Value, -id, -Number) %>%
  unite(Column, Type, Number, sep = "") %>%
  spread(Column, Value) %>%
  ungroup() %>%
  as.data.frame()
Joined
#    id freq1 freq2 sev1 sev2
# 1 111  0.00   1.0 2.00  2.0
# 2 222  1.25   5.2 3.25  5.6
# 3 333  4.00   3.0 5.00  2.0

数据

RMS1 <- read.table(text = "id freq1 sev1 count1 freq2 sev2 count2
111 0    2    50     1     2    25
222 1    3    75     2     4    50
", header = TRUE)

RMS2 <- read.table(text = "id freq1 sev1 count1 freq2 sev2 count2
222 2    4    25     6     6    200
                   333 4    5    60     3     2    20
                   ", header = TRUE)

【讨论】:

  • 此答案之所以出色的部分原因在于,只要命名方案一致,它就可以在任意数量的列 freq1、freq2、freq3 等上工作。
  • @Brandon 谢谢。是的。我希望答案能够在不指定列名或数字的情况下处理多个组。
【解决方案2】:

1) dplyr rbind 将两个输入数据帧放在一起,然后由id 分组执行一个 每个所需列的加权平均值:

library(dplyr)

RMS1 %>%
     rbind(RMS2) %>%
     group_by(id) %>%
     summarize(freq1 = weighted.mean(freq1, count1),
               sev1 = weighted.mean(sev1, count1),
               freq2 = weighted.mean(freq2, count2),
               sev2 = weighted.mean(sev2, count2)) %>%
     ungroup

给予:

# A tibble: 3 x 5
     id freq1  sev1 freq2  sev2
  <int> <dbl> <dbl> <dbl> <dbl>
1   111  0     2.00  1.00  2.00
2   222  1.25  3.25  5.20  5.60
3   333  4.00  5.00  3.00  2.00

2) sqldf 另一种使用 sql 的方法是:

library(sqldf)
sqldf("select id, 
              sum(count1 * freq1 + 0.0) / sum(count1) freq1,
              sum(count1 * sev1 + 0.0)  / sum(count1) sev1,
              sum(count2 * freq2 + 0.0) / sum(count2) freq2,
              sum(count2 * sev2 + 0.0)  / sum(count2) sev2
       from (select * from RMS1 union select * from RMS2)
       group by id", method = "raw")

给予:

   id freq1 sev1 freq2 sev2
1 111  0.00 2.00   1.0  2.0
2 222  1.25 3.25   5.2  5.6
3 333  4.00 5.00   3.0  2.0

注意

可重现形式的输入是:

Lines1 <- "
id freq1 sev1 count1 freq2 sev2 count2
111 0    2    50     1     2    25
222 1    3    75     2     4    50"
RMS1 <- read.table(text = Lines1, header = TRUE)

Lines2 <- "
id freq1 sev1 count1 freq2 sev2 count2
222 2    4    25     6     6    200
333 4    5    60     3     2    20"
RMS2 <- read.table(text = Lines2, header = TRUE)75 + 25)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多