首页 > 解决方案 > 使用循环 [R] 为每个四分位数组分配中值

问题描述

我需要将数值变量分类为四分位数,并使用循环为四分位数组分配中值(因为我的原始数据集有很多变量)。

我打算对许多变量进行以下操作:

data(iris)
iris%>%mutate(Sepal.Lengthq=as.factor(ntile(Sepal.Length,4)))%>%
  group_by(Sepal.Lengthq)%>%
  mutate(Sepal.Lengthq_median=median(Sepal.Length,na.rm=T)) 

我需要循环,所以我写了如下代码:

quartilization=c("Sepal.Length","Sepal.Width")

for (i in seq_along(quartilization)){
  iris2=iris %>% 
    mutate(!!str_c(quartilization[i],"q"):=ntile(.[[quartilization[i]]],4)) %>% 
    group_by_at(vars(one_of(!!str_c(quartilization[i],"q")))) %>% 
    mutate(!!str_c(quartilization[i],"qn"):=median(.[[quartilization[i]]],na.rm=T)) %>%
    ungroup()
}

但是,1)它不返回“Sepal.Lengthqn”和 2)“Sepal.Widthqn”在样本中是相同的值。

我觉得中值函数的语法是错误的,但无法修复。

如果有人可以与我分享一些意见,我将不胜感激。谢谢你。

标签: rloopsgroup-bydplyr

解决方案


当您使用.时,您指的是整个数据框,因此您会在所有年份中获得相同的值。用于获取组中的数据.datamedian

我使用map_dfc而不是for循环,因为它更容易更短。我也使用transmute而不是mutate因为mutate每次都返回所有列,而transmute只返回可以绑定到原始数​​据框的更改列。

library(dplyr)
library(purrr)
library(stringr)

quartilization=c("Sepal.Length","Sepal.Width")

bind_cols(iris, map_dfc(quartilization, ~{
            iris %>%
             group_by(!!str_c(.x,"q") := ntile(.[[.x]],4)) %>%
             transmute(!!str_c(.x,"qn"):= median(.data[[.x]],na.rm=TRUE))
}))

推荐阅读