r - 使用 dplyr 按组查找间隔
问题描述
在这个例子中,我有一个带有两个变量的小标题:
- 组变量
gr
- 感兴趣的变量
val
set.seed(123)
df <- tibble(gr = rep(1:3, each = 10),
val = gr + rnorm(30))
目标
我想生成val
使用该函数的离散版本,findInterval
但断点应该是gr
特定的,因为在我的实际数据以及本示例中,分布val
取决于gr
. 使用 的四分位数在每组内确定断点val
。
我做了什么
我首先构造一个嵌套的 tibble,其中包含每个值的断点向量gr
:
df_breakpoints <- bind_cols(gr = 1:3,
purrr::map_dfr(1:3, function(gr) {
c(-Inf, quantile(df$val[df$gr == gr], c(0.25, 0.5, 0.75)), Inf)
})) %>%
nest(bp = -gr) %>%
mutate(bp = purrr::map(.$bp, unlist))
然后我加入它df
:
df <- inner_join(df, df_breakpoints, by = "gr")
我定义离散变量的第一个猜测lvl
是
df %>% mutate(lvl = findInterval(x = val, vec = bp))
它产生错误
Error : Problem with `mutate()` input `lvl2`.
x 'vec' must be sorted non-decreasingly and not contain NAs
ℹ Input `lvl` is `findInterval(x = val, vec = bp)`.
然后我尝试了
df$lvl <- purrr::imap_dbl(1:nrow(df),
~findInterval(x = df$val[.x], vec = df$bp[[.x]]))
或者
df %>% mutate(lvl = purrr::map2_int(df$val, df$bp, findInterval))
它确实有效。然而,它是非常低效的。使用我的实际数据(120 万行)需要几分钟才能运行。我想有比在行上迭代更好的方法。任何想法?
解决方案
您可以在group_by
+mutate
步骤中执行此操作 -
library(dplyr)
df %>%
group_by(gr) %>%
mutate(breakpoints = findInterval(val,
c(-Inf, quantile(val, c(0.25, 0.5, 0.75)), Inf))) %>%
ungroup
# gr val breakpoints
# <int> <dbl> <int>
# 1 1 0.440 1
# 2 1 0.770 2
# 3 1 2.56 4
# 4 1 1.07 3
# 5 1 1.13 3
# 6 1 2.72 4
# 7 1 1.46 4
# 8 1 -0.265 1
# 9 1 0.313 1
#10 1 0.554 2
# … with 20 more rows
findInterval
分别适用于每个gr
。
推荐阅读
- linux - Make install 在终端命令中成功,但在 shell 脚本中失败
- java - 获取 java.lang.OutOfMemoryError:Jboss 上的 java 堆空间
- flutter - Flutter - 类'QuerySnapshot'没有实例方法'document'
- ios - 数组对象的过滤字典
- csv - 将空格分隔的文本文件加载到 MariaDB 数据库表中
- wpf - 我应该在哪个窗口中实例化我的对象?
- ios - 如何在iOS中根据时间更改获取访问位置权限值?
- flutter - Flutter:如何在没有 mp3 扩展的情况下流式传输由 http url 提供的实时音频
- javascript - 单击重叠区域时如何触发两个元素的单击
- go - 返回消息列表