r - 根据组属性过滤组中的行
问题描述
假设我有一个带有分组变量和逻辑变量的小标题,该变量指示一行是否是该组的主要响应。
我想做以下事情:
- 如果 a 中的任何行
group
被标记为is_primary
保留该行但组中的其他行都没有 - 如果没有行
group
标记为is_primary
,则保留所有行 - 根据上述过滤行
以下是一些示例数据:
library(tidyverse)
data <- tibble(group=c("A","A","A","B","B","C","C","C","C"),
is_primary=c(FALSE, FALSE, FALSE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE),
value=c(1,2,3,4,5,6,7,8,9))
在上面的示例中,我想保留所有A
行,因为没有带有的行,is_primary==TRUE
只保留第二B
行,并保留最后两C
行。
我认为明显的解决方案是:
data %>%
group_by(group) %>%
mutate(keep_row=ifelse(any(is_primary),is_primary,TRUE))
但这会导致以下结果,不符合上述标准。
# A tibble: 9 x 4
# Groups: group [3]
group is_primary value keep_row
<chr> <lgl> <dbl> <lgl>
1 A FALSE 1 TRUE
2 A FALSE 2 TRUE
3 A FALSE 3 TRUE
4 B FALSE 4 FALSE
5 B TRUE 5 FALSE
6 C FALSE 6 FALSE
7 C FALSE 7 FALSE
8 C TRUE 8 FALSE
9 C TRUE 9 FALSE
但是,如果我创建一个指示该组是否具有主键的中间变量,它就可以工作。
data %>%
group_by(group) %>%
mutate(has_primary=ifelse(any(is_primary),TRUE,FALSE)) %>%
mutate(keep_row=ifelse(has_primary,is_primary,TRUE))
这导致keep_row
正确:
# A tibble: 9 x 5
# Groups: group [3]
group is_primary value has_primary keep_row
<chr> <lgl> <dbl> <lgl> <lgl>
1 A FALSE 1 FALSE TRUE
2 A FALSE 2 FALSE TRUE
3 A FALSE 3 FALSE TRUE
4 B FALSE 4 TRUE FALSE
5 B TRUE 5 TRUE TRUE
6 C FALSE 6 TRUE FALSE
7 C FALSE 7 TRUE FALSE
8 C TRUE 8 TRUE TRUE
9 C TRUE 9 TRUE TRUE
ifelse
第一个解决方案不起作用是怎么回事?
解决方案
if/else
当“is_primary”中没有 TRUE 元素时,我们可以使用条件返回行,或者else
仅返回“is_primary”为 TRUE 的行
library(dplyr)
data %>%
group_by(group) %>%
filter(if(!any(is_primary)) TRUE else is_primary)
# A tibble: 6 x 3
# Groups: group [3]
# group is_primary value
# <chr> <lgl> <dbl>
#1 A FALSE 1
#2 A FALSE 2
#3 A FALSE 3
#4 B TRUE 5
#5 C TRUE 8
#6 C TRUE 9
也可以通过|
条件来完成
data %>%
group_by(group) %>%
filter(!any(is_primary) | is_primary)
# A tibble: 6 x 3
# Groups: group [3]
# group is_primary value
# <chr> <lgl> <dbl>
#1 A FALSE 1
#2 A FALSE 2
#3 A FALSE 3
#4 B TRUE 5
#5 C TRUE 8
#6 C TRUE 9
或者另一种选择是
data %>%
group_by(group) %>%
filter(sum(is_primary) == 0 | is_primary)
# A tibble: 6 x 3
# Groups: group [3]
# group is_primary value
# <chr> <lgl> <dbl>
#1 A FALSE 1
#2 A FALSE 2
#3 A FALSE 3
#4 B TRUE 5
#5 C TRUE 8
#6 C TRUE 9
或使用slice
data %>%
group_by(group) %>%
slice(if(!any(is_primary)) row_number() else which(is_primary))
上面的一个data.table
选项是
library(data.table)
setDT(data)[data[, .I[!any(is_primary)|is_primary], by = group]$V1]
或使用base R
data[with(data, !ave(is_primary, group, FUN = any) | is_primary),]
的问题ifelse
是,根据?ifelse
ifelse(测试,是,否)
如果是或否太短,它们的元素将被回收。当且仅当任何测试元素为真时才会评估 yes ,并且类似地为 no。
在OP的代码中
ifelse(any(is_primary),TRUE,FALSE)
any
返回 1 的逻辑向量length
。根据?any
该值是长度为 1 的逻辑向量。
根据上面的ifelse
文档,这些值被回收
推荐阅读
- swift - 图像未在 Alamofire 中使用 multipartformdata 上传到服务器
- kotlin - 作业问题 - 我做错了什么?
- java - 异常是 java.net.ProtocolException:无效的 HTTP 方法:PATCH
- html - 在没有浮动的情况下将元素彼此相邻定位不能正确排列在顶部
- php - 是否可以从网站自动更新“Google 我的商家”信息?
- java - 当数据库不可用但所有数据都被缓存时,防止 Hibernate / Spring 失败
- amazon-sagemaker - 如何在 AWS Sagemaker Studio 上挂载 EFS 卷
- java - JSONObject 到 ArrayList 方括号丢失
- .htaccess - 如何重定向其中包含 %something% 的 URL
- java - ns 不存在,com.mongodb.MongoCommandException