使用dplyr创建字符串列表

时间:2018-10-11 15:09:35

标签: r dataframe dplyr

我想在R中创建一个新列,该列根据是否将多个列标记为“ X”来连接多个字符串。

这是我的数据:

Column1   Column2   Column3   Column4
      X         X         X         
      X                   X         X
      X                             X

我想创建一个新的Column5,如果输入了“ X”,它将包括以下各项:

Column1: 'Texas'
Column2: 'California'
Column3: 'New Jersey'
Column4: 'Oklahoma'

我可以用R中的很多代码来做到这一点,但是我认为使用dplyr可以做到更简洁。

3 个答案:

答案 0 :(得分:1)

这是一种可行的方法:

df = data_frame(c1='x', c2=c('x', NA, NA), c3=c('x', 'x', NA), c4=c(NA, 'x', 'x'))
values = c('TX', 'CA', 'NJ', 'OK')
df$c5 = sapply(df, function(x) !is.na(x)) %>% 
    apply(MARGIN=1, FUN=function(x) paste(values[x], collapse=', '))
df

# A tibble: 3 x 5
  c1    c2    c3    c4    c5                           
  <chr> <chr> <chr> <chr> <chr>                        
1 x     x     x     NA    Texas, California, New Jersey
2 x     NA    x     x     Texas, New Jersey, Oklahoma  
3 x     NA    NA    x     Texas, Oklahoma 

sapply循环遍历数据帧,以检查该值是否丢失,以获取TRUE / FALSE值的矩阵。然后将该矩阵循环,将T / F值的行传递到匿名函数中,该匿名函数索引values并粘贴结果。链接的sapplyapply函数的输出是您要寻找的字符串的向量,这些字符串的长度等于df中的行数。因此,您可以将其设置为新列。希望有道理。

答案 1 :(得分:1)

df <- data.frame(c1 = c(T,T,T),
                 c2 = c(T,F,F),
                 c3 = c(T,T,F),
                 c4 = c(F,T,T))

状态名称与对应列的顺序相同的向量。

sts = c('Texas', 'California', 'New Jersey', "Oklahoma")

现在,您可以测试每一列以获得TRUE列的索引,然后从sts向量中获取相应的状态并将它们paste一起捕获。

在上面的示例中,数据帧包含TRUEFALSE,但是如果您想使用character值(例如'X')来选择单元格,例如,只需将which语句中的测试从== TRUE更改为== 'X'

请注意,当前这需要您指定列名称。 (这样做的好处是,如果您不想再考虑其他列,则不会有任何问题)

df %>%
    rowwise() %>%
    mutate(c5 = paste0(sts[which(c(c1,c2,c3,c4) == TRUE)], collapse = ', '))

Source: local data frame [3 x 5]
Groups: <by row>

# A tibble: 3 x 5
  c1    c2    c3    c4    c5                           
  <lgl> <lgl> <lgl> <lgl> <chr>                        
1 TRUE  TRUE  TRUE  FALSE Texas, California, New Jersey
2 TRUE  FALSE TRUE  TRUE  Texas, New Jersey, Oklahoma  
3 TRUE  FALSE FALSE TRUE  Texas, Oklahoma      

答案 2 :(得分:1)

您可能需要根据数据类型进行一些调整-我在此处粘贴了内容,即没有选中标记的列只是空白。

我使用的方法是创建行号以标识您开始使用的观察结果,将其转换为长形数据,按行号分组,查找已选中的状态,将它们折叠成一个字符串,然后整形回到宽格式。之所以这样做,是因为它将很好地扩展-不管有多少状态,因为我没有做类似Texas == "X" & California == "X" & ...的事情,而这不需要硬编码。

第一步是使用tidyr::gather,因此您将获得行,状态的所有可能值以及对勾或空白。

library(tidyverse)

df <- "Column1   Column2   Column3   Column4
      X         X         X         
      X                   X         X
      X                             X" %>% read_table()

df %>%
  setNames(c("Texas", "California", "New Jersey", "Oklahoma")) %>%
  mutate(row = row_number()) %>%
  gather(key = state, value = value, -row)
#> # A tibble: 12 x 3
#>      row state      value
#>    <int> <chr>      <chr>
#>  1     1 Texas      X    
#>  2     2 Texas      X    
#>  3     3 Texas      X    
#>  4     1 California X    
#>  5     2 California ""   
#>  6     3 California ""   
#>  7     1 New Jersey X    
#>  8     2 New Jersey X    
#>  9     3 New Jersey ""   
#> 10     1 Oklahoma   ""   
#> 11     2 Oklahoma   X    
#> 12     3 Oklahoma   X

然后,我将行号分组,并使用stringr便捷功能。 str_which(value, "^X$")查找value包含正则表达式^X$的位置。将其用作state的索引可获取state中与value中的X对应的条目。然后,我将这些字符串折叠到单个字符串列中,并使用tidyr::spread将其重新设置为宽格式。

df %>%
  setNames(c("Texas", "California", "New Jersey", "Oklahoma")) %>%
  mutate(row = row_number()) %>%
  gather(key = state, value = value, -row) %>%
  group_by(row) %>%
  mutate(states = state[str_which(value, "^X$")] %>% paste(collapse = ", ")) %>%
  spread(key = state, value = value)
#> # A tibble: 3 x 6
#> # Groups:   row [3]
#>     row states                      California `New Jersey` Oklahoma Texas
#>   <int> <chr>                       <chr>      <chr>        <chr>    <chr>
#> 1     1 Texas, California, New Jer… X          X            ""       X    
#> 2     2 Texas, New Jersey, Oklahoma ""         X            X        X    
#> 3     3 Texas, Oklahoma             ""         ""           X        X

reprex package(v0.2.1)于2018-10-11创建