gpt4 book ai didi

r - 根据组属性过滤组中的行

转载 作者:行者123 更新时间:2023-12-01 10:19:10 25 4
gpt4 key购买 nike

假设我有一个带有分组变量和逻辑变量的小标题,该变量指示一行是否是该组的主要响应。

我想做以下事情:

  1. 如果 group 中的任何行被标记为 is_primary,则保留该行,但组中的其他行不保留
  2. 如果 group 中没有行标记为 is_primary,则全部保留
  3. 根据上述过滤行

以下是一些示例数据:

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' 所在的行是的

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(test, yes, no)

If yes or no are too short, their elements are recycled. yes will be evaluated if and only if any element of test is true, and analogously for no.

在 OP 的代码中

 ifelse(any(is_primary),TRUE,FALSE)

any 返回一个length 1的逻辑向量。根据?any

The value is a logical vector of length one.

根据上面的ifelse文档,这些值被回收

关于r - 根据组属性过滤组中的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56860548/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com