dplyr & tibble - создает новый столбец в соответствии со значениями в столбце списка - PullRequest
1 голос
/ 21 марта 2019

У меня есть tibble dataframe следующим образом:

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" all"=> результат равен значению Y
- если значение" Z "находится в" all "=> результат равен значению Z
- иначе результат равен" none "

Я пробовалследующий код с синтаксисом 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  

РЕДАКТИРОВАТЬ

Одна из проблем состоит в том, чтобы отменить перечисление значений в списке столбцов, как указано Ронак Шах .Но даже при таком решении поведение похоже на то, что при работе со списком столбцов будут учитываться все значения столбца, а не только значения строки.

Вот что я получаю с предложенным решением и отредактированными данными:

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 

Ответы [ 2 ]

4 голосов
/ 21 марта 2019

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  
0 голосов
/ 21 марта 2019

Я использовал 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")))

Это производит

enter image description here

...