【问题标题】:dplyr & tibble - Create a new column according to values in a list columndplyr & tibble - 根据列表列中的值创建一个新列
【发布时间】:2019-08-12 02:15:13
【问题描述】:

我有一个如下的 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 

【问题讨论】:

  • data %&gt;% rowwise() %&gt;% mutate(result = case_when(Y %in% unlist(all) ~ Y, Z %in% unlist(all) ~ Z,TRUE ~ "none"))应该做你想做的事

标签: r dplyr tibble


【解决方案1】:

all 列实际上是list,不能直接比较列表列中的值。

例如,

 "a" %in% list(c("a", "b"))
#[1] FALSE

您需要unlistflatten_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  

【讨论】:

  • 它似乎也没有像我预期的那样工作。这是我的错,我没有提供正确的数据以实现可重复性。似乎对“all”列的任何操作都对列的所有值进行操作,而不仅仅是一行的值。我将编辑我的帖子以使其更清晰。
  • @Meshuggahat 我们可以加rowwise,更新答案。
【解决方案2】:

我已经使用ifelsemapplyany 遍历列表并根据给定条件生成值,如下所示

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")))

这会产生

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 2020-04-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 2015-12-02
    • 1970-01-01
    • 2018-06-20
    相关资源
    最近更新 更多