r - 组为空时 data.table 中的子集
问题描述
对于这些数据
library(data.table)
set.seed(42)
dat <- data.table(id=1:12, group=rep(1:3, each=4), x=rnorm(12))
> dat
id group x
1: 1 1 1.37095845
2: 2 1 -0.56469817
3: 3 1 0.36312841
4: 4 1 0.63286260
5: 5 2 0.40426832
6: 6 2 -0.10612452
7: 7 2 1.51152200
8: 8 2 -0.09465904
9: 9 3 2.01842371
10: 10 3 -0.06271410
11: 11 3 1.30486965
12: 12 3 2.28664539
我的目标是从每个组中获取x
大于某个阈值的第一个 id,例如x>1.5
。
> dat[x>1.5, .SD[1], by=group]
group id x
1: 2 7 1.511522
2: 3 9 2.018424
确实是正确的,但我对它默默地没有为第 1 组产生任何结果这一事实感到不满。相反,我希望它产生每个没有 id 满足条件的组的最后一个 id。我看到我可以分两步实现
> tmp <- dat[x>1.5, .SD[1], by=group]
> rbind(tmp,dat[!group%in%tmp$group,.SD[.N], by=group])
group id x
1: 2 7 1.5115220
2: 3 9 2.0184237
3: 1 4 0.6328626
但我确信我没有充分利用这里的 data.table 功能,这必须允许更优雅的解决方案。
解决方案
使用data.table
,我们可以逐组检查条件和子集。
library(data.table)
dat[dat[, if(any(x>1.5)) .I[which.max(x > 1.5)] else .I[.N], by=group]$V1]
# id group x
#1: 4 1 0.6328626
#2: 7 2 1.5115220
#3: 9 3 2.0184237
,的dplyr
翻译将是
library(dplyr)
dat %>%
group_by(group) %>%
slice(if(any(x > 1.5)) which.max(x > 1.5) else n())
或者更高效
dat[, .SD[{temp = x > 1.5; if (any(temp)) which.max(temp) else .N}], by = group]
感谢@IceCreamTouCan、@sindri_baldur 和@jangorecki 为改进此答案提出的宝贵建议。
推荐阅读
- c++ - 在 C++ 中,运算符 sizeof 返回什么数据类型?
- ruby - Ruby 中的问号而不是非 ASCII 符号使用 Windows 终端
- sql - 使用 row_number 使用前一行值更新列值
- i3 - 是否可以在同一屏幕的顶部有一个 polybar(或任何其他 i3bar),而另一个在同一屏幕的底部?
- c# - 如何在界面之间进行转换?
- python - 具有 3 个变量的开关盒
- game-physics - Defold 物理,呆滞
- database - 具有自定义输出的条件聚合
- python - SQLAlchemy 中的 Backref 返回空列表
- ios - SwiftUI HStack 不会移到最顶端?