【问题标题】:average column rows according to value in other columns根据其他列中的值平均列行
【发布时间】:2020-03-05 10:38:26
【问题描述】:

这是我正在处理的数据:

library(RCurl)
x <- getURL("https://raw.githubusercontent.com/dothemathonthatone/maps/master/main_test.csv")
maindf <- read.csv(text = x)

maindf_1 <- maindf %>% 
             dplyr::select(year, regional_schlüssel, age_group, fee_per_inc, fert_total, daily_hours, low_fee, middle_fee, high_fee) 

head(maindf_1)

year    regional_schlüssel  fee_per_inc fert_total  daily_hours low_fee middle_fee  high_fee
2006    12246436188 0.000000000 0.02905331  8   1   0   0
2006    12246436188 0.002770760 0.02905331  8   1   0   0
2006    12246436188 0.003857333 0.02905331  8   1   0   0
2006    12246436188 0.004237633 0.02905331  8   0   1   0
2006    12246436188 0.004482112 0.02905331  8   0   1   0
2006    12246436188 0.005085077 0.02905331  8   0   1   0 

为了准备面板回归的数据,我想根据最后三列对第 4 列 fee_per_inc 中的非零值进行平均;例如,

year    regional_schlüssel  age_group   fee_per_inc fert_total  daily_hours low_fee middle_fee  high_fee
2006    12246436188 -8  0.000000000 0.02905331  8   .003314047  0   0
2006    12246436188 -8  0.002770760 0.02905331  8   .003314047  0   0
2006    12246436188 -8  0.003857333 0.02905331  8   .003314047  0   0
2006    12246436188 -8  0.004237633 0.02905331  8   0   .004601607  0
2006    12246436188 -8  0.004482112 0.02905331  8   0   .004601607  0
2006    12246436188 -8  0.005085077 0.02905331  8   0   .004601607  0  

然后删除最后三行中的零:

year    regional_schlüssel  age_group   fee_per_inc fert_total  daily_hours low_fee middle_fee  high_fee
2006    12246436188 -8  0.000000000 0.02905331  8   .003314047  .004601607  0
2006    12246436188 -8  0.002770760 0.02905331  8   .003314047  .004601607  0
2006    12246436188 -8  0.003857333 0.02905331  8   .003314047  .004601607  0

除了在这个例子中最后一行仍然有零。 完成此操作后,我可以删除 fee_per_inc、冗余行并进入面板回归。

【问题讨论】:

  • 您需要maindf_1 %&gt;% group_by(regional_schlüssel) %&gt;% mutate_at(vars(ends_with('fee')), ~replace(., . != 0, mean(na.omit(.)))) 吗?这会将非零值替换为该组中该列的非零值mean
  • @RonakShah 谢谢,但这在运行代码时也会带来一些问题。数字未正确汇总
  • 您能解释一下您是如何执行聚合的吗?哪些列应该更改为什么值?
  • @RonakShah 感谢您的提问:在上面的第一个数据帧中,0.0027707600.003857333 的平均值将位于列 low_fee 的前三行;那么0.0042376330.0044821120.005085077 值的平均值将进入middle_fee 的列中。
  • 如上例中的最后一个数据框。

标签: r dplyr


【解决方案1】:

这里只是一个新手,但也许是这样的?

maindf_2 <- maindf_1 %>% 
  mutate(fee_per_inc = ifelse(fee_per_inc==0,NA, fee_per_inc)) %>% 
  group_by(low_fee, middle_fee, high_fee) %>% 
  mutate(low_fee_avg = ifelse(low_fee !=0, mean(fee_per_inc, na.rm = T), NA),
         mid_fee_avg = ifelse(middle_fee !=0, mean(fee_per_inc, na.rm = T), NA),
         high_fee_avg = ifelse(high_fee !=0, mean(fee_per_inc, na.rm = T), NA)
  ) %>% 
  ungroup() %>% 
  select(-ends_with("_fee"))

【讨论】:

  • 您好 Enrico,感谢您的回复。我运行了代码并查看了输出。我认为数学不太对劲。可能我还需要group_by regional_schlüssel
  • 嘿,恐怕我无法确定您的数据必须如何分组才能获得您想要的结果。对于显示的示例 region_schlüssel、year 和其他列,我有 4 条记录,low_fee == 1 和 fee_per_inc !=0,它们的平均值不是 0.003314047。我在这里想念什么?谢谢
  • 是的,值得一提。分组在 age_group、year 和 daily_hours 上。 id 是 region_schlüssel。
  • low_fee、middle_fee 和 high_fee 是 fee_per_inc 的分位数,按 region_schlüssel 分组。
  • 现在我明白了。无论列值如何,每组行本身都是一个“孤岛”。这就是为什么在 Ronan 的解决方案中,第 1-3 行的平均值与第 7-9 行的平均值不同,尽管两组之间的所有分组变量都是相等的。我只是假设每一行都具有相同的分组变量,并且(例如)low_fee == 1 必须一起平均
【解决方案2】:

执行此操作的一种方法是将数据重塑为长格式,删除具有 0 值的行,按 regional_schlüssel 和唯一列名分组。我们可以取mean 的非零fee_per_inc 值,将数据转换为宽格式并删除不需要的列。

library(dplyr)
library(tidyr)


maindf_1 %>%
  pivot_longer(cols = ends_with('fee')) %>%
  filter(value != 0) %>%
  group_by(regional_schlüssel, grp = data.table::rleid(name)) %>%
  mutate(value =  mean(fee_per_inc[fee_per_inc != 0],  na.rm = TRUE), 
         row = row_number()) %>%
  pivot_wider(values_fill = list(value  =  0)) %>%
  ungroup() %>%
  select(-grp, -fee_per_inc, -row)


#    year regional_schlüssel age_group fert_total daily_hours low_fee middle_fee high_fee
#   <int>              <dbl> <fct>          <dbl> <fct>         <dbl>      <dbl>    <dbl>
# 1  2006       12246436188. -8            0.0291 8           0.00331    0              0
# 2  2006       12246436188. -8            0.0291 8           0.00331    0              0
# 3  2006       12246436188. -8            0.0291 8           0.00331    0              0
# 4  2006       12246436188. -8            0.0291 8           0          0.00460        0
# 5  2006       12246436188. -8            0.0291 8           0          0.00460        0
# 6  2006       12246436188. -8            0.0291 8           0          0.00460        0
# 7  2006       12246436188. -8            0.0291 8           0.00197    0              0
# 8  2006       12246436188. -8            0.0291 8           0.00197    0              0
# 9  2006       12246436188. -8            0.0291 8           0.00197    0              0
#10  2006       12246436188. -8            0.0291 8           0          0.00308        0
 # … with 9,907 more rows

【讨论】:

  • 感谢您的回答。我添加了一个%&gt;% unique(),它更接近我正在寻找的东西。但是,你知道我如何向上移动零,即0.0291 8 0.00331 0.004600.0291 8 0.00331 0.004600.0291 8 0.00331 0.00460
  • @MichaelPerdue 那么您将如何管理其他列中的值?另外,如果一列有 10 个 0,另一列有 8 个,你将如何平衡这些列?我猜您的意思是将mutate_at(vars(ends_with('fee')), ~.[. != 0]) 添加到管道中,但正如您所见,它返回一个错误,因为输出到该管道的行数少于原始maindf_1
猜你喜欢
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 1970-01-01
  • 2021-06-07
相关资源
最近更新 更多