r - 使用 pivot_wider 从没有 values_from 列的逗号分隔向量创建唯一列

标签 r tidyr

我有以下用例 pivot_wider :
我有一个用逗号分隔的字符串的数据集。我想为每个逗号分隔值创建唯一的列,就像一个虚拟变量采用 1 s(存在值)和 0 s(值不存在)。
我可以使用下面显示的方法来做到这一点。但是,我认为这是一种解决方法,因为我需要添加一列 value = 1然后我在 pivot_wider 中使用它s values_from争论。我尝试使用 values_from = 1没有先创建一个新列(我认为 pivot_wider 可以动态创建值),但结果是 values_from使用 tidyeval 并改为选择第一列。我也试过根本不指定参数,但这也不起作用。
有没有更好的方法来使用 pivot_wider不创建取值 1 的列对于所有行?由于我真的经常使用这种“解决方法”,我只是想知道是否有更官方的方法来达到相同的结果。

library(dplyr)
library(tidyr)

# data generating function
create_codes <- function(inp, len) {
  
  size <- round(runif(len, 1, 5))
  
  res <- vapply(seq_len(len),
                FUN.VALUE = character(1),
                FUN = function(x) {
                  paste(sample(inp, size[x]), collapse = ", ")
                })
  
}

# toy data
set.seed(123)
dat <- tibble(id = 1:100,
              codes = create_codes(10:25, 100))

# transform codes to unique columns
dat %>% 
  mutate(codes2 = strsplit(codes, ", "),
         # can pivot_wider work without this 'workaround' => 'value = 1'?
         value = 1) %>% 
  unnest(codes2) %>%
  arrange(codes2) %>% 
  pivot_wider(names_from = codes2,
              names_prefix = "code_",
              names_repair = "universal",
              values_from = value,
              values_fill = 0) 

#> # A tibble: 100 x 18
#>       id codes code_10 code_11 code_12 code_13 code_14 code_15 code_16 code_17
#>    <int> <chr>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
#>  1    11 13, …       1       0       1       1       0       1       0       0
#>  2    13 23, …       1       0       0       0       0       0       0       1
#>  3    25 10, …       1       0       0       1       0       0       0       1
#>  4    30 15, …       1       0       0       0       0       1       0       0
#>  5    37 14, …       1       0       0       0       1       0       1       0
#>  6    47 20, …       1       0       0       0       0       0       0       0
#>  7    59 20, …       1       0       0       0       0       0       0       0
#>  8    60 19, …       1       0       0       0       0       0       0       0
#>  9    66 10, …       1       0       0       0       1       0       0       0
#> 10    67 13, …       1       0       1       1       0       0       0       0
#> # … with 90 more rows, and 8 more variables: code_18 <dbl>, code_19 <dbl>,
#> #   code_20 <dbl>, code_21 <dbl>, code_22 <dbl>, code_23 <dbl>, code_24 <dbl>,
#> #   code_25 <dbl>
创建于 2021-02-16 由 reprex package (v0.3.0)

最佳答案

我们可以使用 values_fnlength这将绕过创建列“值”的需要。注意,这里我们假设 OP 的问题即将绕过 value 的创建。列而不是关于更改 strsplit

library(dplyr)
library(tidyr)
dat %>% 
     mutate(codes2 = strsplit(codes, ", ")) %>%
     unnest(codes2) %>% 
     arrange(codes2) %>%  
     pivot_wider(names_from = codes2,
            names_prefix = "code_",
            names_repair = "universal", values_from = codes2, 
        values_fill = 0, values_fn = length)
-输出
# A tibble: 100 x 18
      id codes code_10 code_11 code_12 code_13 code_14 code_15 code_16 code_17 code_18 code_19 code_20
   <int> <chr>   <int>   <int>   <int>   <int>   <int>   <int>   <int>   <int>   <int>   <int>   <int>
 1    11 13, …       1       0       1       1       0       1       0       0       0       0       0
 2    13 23, …       1       0       0       0       0       0       0       1       0       0       0
 3    25 10, …       1       0       0       1       0       0       0       1       0       0       0
 4    30 15, …       1       0       0       0       0       1       0       0       0       0       0
 5    37 14, …       1       0       0       0       1       0       1       0       0       0       0
 6    47 20, …       1       0       0       0       0       0       0       0       0       0       1
 7    59 20, …       1       0       0       0       0       0       0       0       0       1       1
 8    60 19, …       1       0       0       0       0       0       0       0       0       1       0
 9    66 10, …       1       0       0       0       1       0       0       0       1       0       0
10    67 13, …       1       0       1       1       0       0       0       0       1       0       0
# … with 90 more rows, and 5 more variables: code_21 <int>, code_22 <int>, code_23 <int>, code_24 <int>,
#   code_25 <int>

如果有重复,那么我们也可以传递一个 lambda 函数
dat %>% 
     mutate(codes2 = strsplit(codes, ", ")) %>%
     unnest(codes2) %>% 
     arrange(codes2) %>%  
     pivot_wider(names_from = codes2,
            names_prefix = "code_",
            names_repair = "universal", values_from = codes2, 
        values_fill = 0, values_fn = list(codes2 = ~ +(length(.) > 0)))

或者可以通过 cSplit_e 更轻松地完成
library(splitstackshape)
cSplit_e(dat, "codes", sep=",", type = 'character', fill = 0, drop = TRUE)

关于r - 使用 pivot_wider 从没有 values_from 列的逗号分隔向量创建唯一列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66233505/

相关文章:

R Shiny 选择变量基于 checkboxGroupInput

r - 如何关联回自组织 map 中的原始数据点

r - 多次子集数据框

R - tidyr - 变异并传播多列

r - 将子集列粘贴在一起

R;如何解决 "expired PostgreSQLConnection"错误?

r - 错误 : Could not find build tools necessary to build

r - 在 pivot_longer 的 names_pattern 参数中为通过前缀的存在或不存在区分的多个变量编码正则表达式

r - 达到阈值时 dplyr 重置计数器

r - 将 ddply 转换为 dplyr 和 tidyr 代码(变异、联合、传播)