【问题标题】:Subset a dataframe based on quantiles根据分位数对数据框进行子集
【发布时间】:2019-10-16 19:35:50
【问题描述】:

如果我有这个数据框:

df <- data.frame(time = seq(as.Date('2000-01-01'), length.out = 200, by = 'days'),
             a = rnorm(200,8.4, 22), b=rnorm(200,8.4, 22), d= rnorm(200,8.4, 22), 
e=rnorm(200,8.4, 22))

df 进行子集化以使每列的值应高于 10% 百分位但低于 90% 的最简单方法是什么?

我可以使用循环来做到这一点,即:

for (i in names(df[,2:5])){
  print(i)
  column <- df[,c('time', i)]
  q <- unname(quantile(column[,2], probs = c(0.1, 0.9))) # just for one column
  column <- column[column[,2] > q[1] &column[,2] < q[2],]
  df <- merge(df, column, by = 'time', all.x = T)
}

但是有更简单和更优雅的方法可以使用函数或包,如dplyr。谢谢!

【问题讨论】:

  • 嗨,我知道。在这种情况下可以插入 NA

标签: r function dplyr subset


【解决方案1】:

这是dplyr 方法:

library(dplyr)

df %>% 
  mutate_at(vars(a:e), function(x) if_else(between(percent_rank(x), .1, .9), x, NA_real_))

【讨论】:

    【解决方案2】:

    在列上使用sapply 并过滤范围内的值。

    sapply(df[-1], function(x) x[x > quantile(x, 0.1) & x < quantile(x, 0.9)])
    

    向后添加time 列可能会很棘手,因为我们已经过滤了每一行可能代表不同time 的值。

    @Sotos 建议的更好选择是将这些值转换为 NA 而不是过滤

    cbind(df[1], sapply(df[-1], function(i) 
                replace(i, i < quantile(i, 0.1) | i > quantile(i, 0.9), NA)))
    

    【讨论】:

    • 或简单地转换为 NA,sapply(df[-1], function(i) replace(i, i &lt; quantile(i, 0.1) | i &gt; quantile(i, 0.9), NA))
    • 您好,感谢您的提示。不幸的是,我需要返回时间列,因为在此过滤之后我需要完成一些聚合。
    猜你喜欢
    • 2021-07-22
    • 2013-08-15
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 2019-02-16
    相关资源
    最近更新 更多