按(行)对组合过滤
Filter by combination of (row) pairs
我有一个长格式的数据框,我想根据值的唯一组合过滤对。我有一个看起来像这样的数据集:
id <- rep(1:4, each=2)
type <- c("blue", "blue", "red", "yellow", "blue", "red", "red", "yellow")
df <- data.frame(id,type)
df
id type
1 1 blue
2 1 blue
3 2 red
4 2 yellow
5 3 blue
6 3 red
7 4 red
8 4 yellow
假设每个 id 是一个受访者,type 是治疗的组合。个人 1 看到了两个物体,都是蓝色的;个体 2 看到了一个红色物体和一个黄色物体;等等。
我如何保留那些看到 "red" 和 "yellow" 组合的人?如果我按组合 "red" 和 "yellow" 进行过滤,结果数据集应如下所示:
id type
3 2 red
4 2 yellow
7 4 red
8 4 yellow
它应该保留 2 号和 4 号受访者(仅那些看到组合 "red" 和 "yellow" 的受访者)。请注意,它不会保留 3 号受访者,因为她看到了 "blue" 和 "red"(而不是 "red" 和 "yellow")。我该怎么做?
一种解决方案是将数据集重塑为宽格式,按列过滤,然后重新堆叠。但我确信还有另一种方法可以在不重塑数据集的情况下做到这一点。有什么想法吗?
一个dplyr
解决方案是:
library(dplyr)
df <- data_frame(
id = rep(1:4, each = 2),
type = c("blue", "blue", "red", "yellow", "blue", "red", "red", "yellow")
)
types <- c("red", "yellow")
df %>%
group_by(id) %>%
filter(all(types %in% type))
#> # A tibble: 4 x 2
#> # Groups: id [2]
#> id type
#> <int> <chr>
#> 1 2 red
#> 2 2 yellow
#> 3 4 red
#> 4 4 yellow
更新
允许相等的组合,例如blue
、blue
,我们必须将过滤器调用更改为以下内容:
types2 <- c("blue", "blue")
df %>%
group_by(id) %>%
filter(sum(types2 == type) == length(types2))
#> # A tibble: 2 x 2
#> # Groups: id [1]
#> id type
#> <int> <chr>
#> 1 1 blue
#> 2 1 blue
此解决方案还允许不同类型
df %>%
group_by(id) %>%
filter(sum(types == type) == length(types))
#> # A tibble: 4 x 2
#> # Groups: id [2]
#> id type
#> <int> <chr>
#> 1 2 red
#> 2 2 yellow
#> 3 4 red
#> 4 4 yellow
让我们使用 all()
查看组中的所有行是否都匹配一组值。
library(tidyverse)
test_filter <- c("red", "yellow")
df %>%
group_by(id) %>%
filter(all(test_filter %in% type))
# A tibble: 4 x 2
# Groups: id [2]
id type
<int> <fctr>
1 2 red
2 2 yellow
3 4 red
4 4 yellow
我修改了您的数据并执行了以下操作。
df <- data.frame(id = rep(1:4, each=3),
type <- c("blue", "blue", "green", "red", "yellow", "purple",
"blue", "orange", "yellow", "yellow", "pink", "red"),
stringsAsFactors = FALSE)
id type
1 1 blue
2 1 blue
3 1 green
4 2 red
5 2 yellow
6 2 purple
7 3 blue
8 3 orange
9 3 yellow
10 4 yellow
11 4 pink
12 4 red
如您所见,每个 id 有三个观察值。 id 2 和 4 都有 red
和 yellow
。它们也有非目标颜色(即紫色和粉红色)。我想保留这些观察结果。为了完成这个任务,我写了下面的代码。代码可以这样读。 "For each id, check if there is any red
and yellow
using any()
. When both conditions are TRUE, keep all rows for the id."
group_by(df, id) %>%
filter(any(type == "yellow") & any(type == "red"))
id type
4 2 red
5 2 yellow
6 2 purple
10 4 yellow
11 4 pink
12 4 red
使用data.table
:
library(data.table)
setDT(df)
df[, type1 := shift(type, type = "lag"), by = id]
df1 <- df[type == "yellow" & type1 == "red", id]
df <- df[id %in% df1, ]
df[, type1 := NULL]
它给出:
id type
1: 2 red
2: 2 yellow
3: 4 red
4: 4 yellow
我有一个长格式的数据框,我想根据值的唯一组合过滤对。我有一个看起来像这样的数据集:
id <- rep(1:4, each=2)
type <- c("blue", "blue", "red", "yellow", "blue", "red", "red", "yellow")
df <- data.frame(id,type)
df
id type
1 1 blue
2 1 blue
3 2 red
4 2 yellow
5 3 blue
6 3 red
7 4 red
8 4 yellow
假设每个 id 是一个受访者,type 是治疗的组合。个人 1 看到了两个物体,都是蓝色的;个体 2 看到了一个红色物体和一个黄色物体;等等。
我如何保留那些看到 "red" 和 "yellow" 组合的人?如果我按组合 "red" 和 "yellow" 进行过滤,结果数据集应如下所示:
id type
3 2 red
4 2 yellow
7 4 red
8 4 yellow
它应该保留 2 号和 4 号受访者(仅那些看到组合 "red" 和 "yellow" 的受访者)。请注意,它不会保留 3 号受访者,因为她看到了 "blue" 和 "red"(而不是 "red" 和 "yellow")。我该怎么做?
一种解决方案是将数据集重塑为宽格式,按列过滤,然后重新堆叠。但我确信还有另一种方法可以在不重塑数据集的情况下做到这一点。有什么想法吗?
一个dplyr
解决方案是:
library(dplyr)
df <- data_frame(
id = rep(1:4, each = 2),
type = c("blue", "blue", "red", "yellow", "blue", "red", "red", "yellow")
)
types <- c("red", "yellow")
df %>%
group_by(id) %>%
filter(all(types %in% type))
#> # A tibble: 4 x 2
#> # Groups: id [2]
#> id type
#> <int> <chr>
#> 1 2 red
#> 2 2 yellow
#> 3 4 red
#> 4 4 yellow
更新
允许相等的组合,例如blue
、blue
,我们必须将过滤器调用更改为以下内容:
types2 <- c("blue", "blue")
df %>%
group_by(id) %>%
filter(sum(types2 == type) == length(types2))
#> # A tibble: 2 x 2
#> # Groups: id [1]
#> id type
#> <int> <chr>
#> 1 1 blue
#> 2 1 blue
此解决方案还允许不同类型
df %>%
group_by(id) %>%
filter(sum(types == type) == length(types))
#> # A tibble: 4 x 2
#> # Groups: id [2]
#> id type
#> <int> <chr>
#> 1 2 red
#> 2 2 yellow
#> 3 4 red
#> 4 4 yellow
让我们使用 all()
查看组中的所有行是否都匹配一组值。
library(tidyverse)
test_filter <- c("red", "yellow")
df %>%
group_by(id) %>%
filter(all(test_filter %in% type))
# A tibble: 4 x 2
# Groups: id [2]
id type
<int> <fctr>
1 2 red
2 2 yellow
3 4 red
4 4 yellow
我修改了您的数据并执行了以下操作。
df <- data.frame(id = rep(1:4, each=3),
type <- c("blue", "blue", "green", "red", "yellow", "purple",
"blue", "orange", "yellow", "yellow", "pink", "red"),
stringsAsFactors = FALSE)
id type
1 1 blue
2 1 blue
3 1 green
4 2 red
5 2 yellow
6 2 purple
7 3 blue
8 3 orange
9 3 yellow
10 4 yellow
11 4 pink
12 4 red
如您所见,每个 id 有三个观察值。 id 2 和 4 都有 red
和 yellow
。它们也有非目标颜色(即紫色和粉红色)。我想保留这些观察结果。为了完成这个任务,我写了下面的代码。代码可以这样读。 "For each id, check if there is any red
and yellow
using any()
. When both conditions are TRUE, keep all rows for the id."
group_by(df, id) %>%
filter(any(type == "yellow") & any(type == "red"))
id type
4 2 red
5 2 yellow
6 2 purple
10 4 yellow
11 4 pink
12 4 red
使用data.table
:
library(data.table)
setDT(df)
df[, type1 := shift(type, type = "lag"), by = id]
df1 <- df[type == "yellow" & type1 == "red", id]
df <- df[id %in% df1, ]
df[, type1 := NULL]
它给出:
id type
1: 2 red
2: 2 yellow
3: 4 red
4: 4 yellow