dplyr & tibble - 根据列表列中的值创建一个新列
dplyr & tibble - Create a new column according to values in a list column
我有一个 tibble 数据框如下:
data = tibble(X = c("a", "b", "c", "d","c"),
Y = c("a1", "b1", "c1", "d1","c1"),
Z = c("a2", "b2", "c2", "d2","c2"),
all = list(c("a"), c("b"), c("c", "c1"), c("d", "d2"), c("c", "b2")))
我想创建一个新列 "result" 这样每一行 :
- 如果 "Y" 值在 "all" => 结果等于 Y 值
- 如果 "Z" 值在 "all" => 结果等于 Z 值
- 否则结果等于 "none"
我已经尝试使用 dplyr 语法编写以下代码。
data %>%
mutate(result = case_when(Y %in% all ~ Y,
Z %in% all ~ Z,
TRUE ~ "none"))
它没有按预期工作并且 returns:
# A tibble: 4 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [2]> none
2 b b1 b2 <chr [1]> none
3 c c1 c2 <chr [2]> none
4 d d1 d2 <chr [2]> none
当我想获得:
# A tibble: 4 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [2]> none
2 b b1 b2 <chr [1]> none
3 c c1 c2 <chr [2]> c1
4 d d1 d2 <chr [2]> d2
编辑
一个问题是取消列出列列表中的值,如 Ronak Shah 所述。但即使使用此解决方案,其行为就像处理列列表一样会考虑列的所有值,而不仅仅是行的值。
这是我通过建议的解决方案和编辑后的数据获得的结果:
data %>%
mutate(result = case_when(Y %in% flatten_chr(all) ~ Y,
Z %in% flatten_chr(all) ~ Z,
TRUE ~ "none"))
# A tibble: 5 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [1]> none
2 b b1 b2 <chr [1]> b2
3 c c1 c2 <chr [2]> c1
4 d d1 d2 <chr [2]> d2
5 c c1 c2 <chr [2]> c1
什么时候应该 return :
# A tibble: 5 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [1]> none
2 b b1 b2 <chr [1]> none
3 c c1 c2 <chr [2]> c1
4 d d1 d2 <chr [2]> d2
5 c c1 c2 <chr [2]> none
all
列实际上是一个list
,不能直接比较list列中的值。
例如,
"a" %in% list(c("a", "b"))
#[1] FALSE
您需要 unlist
或 flatten_chr
才能正常工作。
"a" %in% unlist(list(c("a", "b")))
#[1] TRUE
"a" %in% flatten_chr(list(c("a", "b")))
#[1] TRUE
所以,现在你可以做
library(tidyverse)
data %>%
mutate(result = case_when(Y %in% flatten_chr(all) ~ Y,
Z %in% flatten_chr(all) ~ Z,
TRUE ~ "none"))
# X Y Z all result
# <chr> <chr> <chr> <list> <chr>
#1 a a1 a2 <chr [2]> none
#2 b b1 b2 <chr [1]> none
#3 c c1 c2 <chr [2]> c1
#4 d d1 d2 <chr [2]> d2
编辑
您可以添加 rowwise
来比较每一行的值。
data %>%
rowwise() %>%
mutate(result = case_when(Y %in% all ~ Y,
Z %in% all ~ Z,
TRUE ~ "none"))
# A tibble: 5 x 5
# X Y Z all result
# <chr> <chr> <chr> <list> <chr>
#1 a a1 a2 <chr [1]> none
#2 b b1 b2 <chr [1]> none
#3 c c1 c2 <chr [2]> c1
#4 d d1 d2 <chr [2]> d2
#5 c c1 c2 <chr [2]> none
我已经使用 ifelse
、mapply
和 any
遍历列表并根据给定条件生成值,如下所示
data$result <- ifelse(unlist(mapply(
data$all,data$Z,
FUN = function(x, y) {
any(x%in% y)
}
)), data$Z, ifelse(unlist(mapply(
data$all, data$Y,
FUN = function(x, y) {
any(x%in% y)
}
)), data$Y, "none"))
#View Data
data
或者:
library(dplyr)
data %>%
mutate(result = ifelse(unlist(mapply(
all,Z,
FUN = function(x,y) {
any(x%in% y)
}
)), Z, ifelse(unlist(mapply(
all,Y,
FUN = function(x, y) {
any(x%in% y)
}
)), Y, "none")))
这会产生
我有一个 tibble 数据框如下:
data = tibble(X = c("a", "b", "c", "d","c"),
Y = c("a1", "b1", "c1", "d1","c1"),
Z = c("a2", "b2", "c2", "d2","c2"),
all = list(c("a"), c("b"), c("c", "c1"), c("d", "d2"), c("c", "b2")))
我想创建一个新列 "result" 这样每一行 :
- 如果 "Y" 值在 "all" => 结果等于 Y 值
- 如果 "Z" 值在 "all" => 结果等于 Z 值
- 否则结果等于 "none"
我已经尝试使用 dplyr 语法编写以下代码。
data %>%
mutate(result = case_when(Y %in% all ~ Y,
Z %in% all ~ Z,
TRUE ~ "none"))
它没有按预期工作并且 returns:
# A tibble: 4 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [2]> none
2 b b1 b2 <chr [1]> none
3 c c1 c2 <chr [2]> none
4 d d1 d2 <chr [2]> none
当我想获得:
# A tibble: 4 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [2]> none
2 b b1 b2 <chr [1]> none
3 c c1 c2 <chr [2]> c1
4 d d1 d2 <chr [2]> d2
编辑
一个问题是取消列出列列表中的值,如 Ronak Shah 所述。但即使使用此解决方案,其行为就像处理列列表一样会考虑列的所有值,而不仅仅是行的值。
这是我通过建议的解决方案和编辑后的数据获得的结果:
data %>%
mutate(result = case_when(Y %in% flatten_chr(all) ~ Y,
Z %in% flatten_chr(all) ~ Z,
TRUE ~ "none"))
# A tibble: 5 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [1]> none
2 b b1 b2 <chr [1]> b2
3 c c1 c2 <chr [2]> c1
4 d d1 d2 <chr [2]> d2
5 c c1 c2 <chr [2]> c1
什么时候应该 return :
# A tibble: 5 x 5
X Y Z all result
<chr> <chr> <chr> <list> <chr>
1 a a1 a2 <chr [1]> none
2 b b1 b2 <chr [1]> none
3 c c1 c2 <chr [2]> c1
4 d d1 d2 <chr [2]> d2
5 c c1 c2 <chr [2]> none
all
列实际上是一个list
,不能直接比较list列中的值。
例如,
"a" %in% list(c("a", "b"))
#[1] FALSE
您需要 unlist
或 flatten_chr
才能正常工作。
"a" %in% unlist(list(c("a", "b")))
#[1] TRUE
"a" %in% flatten_chr(list(c("a", "b")))
#[1] TRUE
所以,现在你可以做
library(tidyverse)
data %>%
mutate(result = case_when(Y %in% flatten_chr(all) ~ Y,
Z %in% flatten_chr(all) ~ Z,
TRUE ~ "none"))
# X Y Z all result
# <chr> <chr> <chr> <list> <chr>
#1 a a1 a2 <chr [2]> none
#2 b b1 b2 <chr [1]> none
#3 c c1 c2 <chr [2]> c1
#4 d d1 d2 <chr [2]> d2
编辑
您可以添加 rowwise
来比较每一行的值。
data %>%
rowwise() %>%
mutate(result = case_when(Y %in% all ~ Y,
Z %in% all ~ Z,
TRUE ~ "none"))
# A tibble: 5 x 5
# X Y Z all result
# <chr> <chr> <chr> <list> <chr>
#1 a a1 a2 <chr [1]> none
#2 b b1 b2 <chr [1]> none
#3 c c1 c2 <chr [2]> c1
#4 d d1 d2 <chr [2]> d2
#5 c c1 c2 <chr [2]> none
我已经使用 ifelse
、mapply
和 any
遍历列表并根据给定条件生成值,如下所示
data$result <- ifelse(unlist(mapply(
data$all,data$Z,
FUN = function(x, y) {
any(x%in% y)
}
)), data$Z, ifelse(unlist(mapply(
data$all, data$Y,
FUN = function(x, y) {
any(x%in% y)
}
)), data$Y, "none"))
#View Data
data
或者:
library(dplyr)
data %>%
mutate(result = ifelse(unlist(mapply(
all,Z,
FUN = function(x,y) {
any(x%in% y)
}
)), Z, ifelse(unlist(mapply(
all,Y,
FUN = function(x, y) {
any(x%in% y)
}
)), Y, "none")))
这会产生