我有一个如下的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")))
我想创建一个新列“结果”,以便每行: - 如果“Y”值在“all”中=>结果等于Y值 - 如果“Z”值在“all”中=>结果等于Z值 - 否则结果等于“无”
我用dplyr语法尝试了以下代码。
data %>%
mutate(result = case_when(Y %in% all ~ Y,
Z %in% all ~ Z,
TRUE ~ "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]> 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
什么时候应该返回:
# 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
,你无法直接比较列表列中的值。
例如,
"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")))
这产生了