将多列分成单独的名称-值对

问题描述 投票:0回答:1

我有:

library("dplyr")

mtcars %>% count(cyl, gear)
#>   cyl gear  n
#> 1   4    3  1
#> 2   4    4  8
#> 3   4    5  2
#> 4   6    3  2
#> 5   6    4  4
#> 6   6    5  1
#> 7   8    3 12
#> 8   8    5  2

我需要什么:

#>   variable1 category1 variable2 category2  n
#> 1       cyl         4      gear         3  1
#> 2       cyl         4      gear         4  8
#> 3       cyl         4      gear         5  2
#> 4       cyl         6      gear         3  2
#> 5       cyl         6      gear         4  4
#> 6       cyl         6      gear         5  1
#> 7       cyl         8      gear         3 12
#> 8       cyl         8      gear         5  2

问题是传递给

cyl
的变量(本例中为
gear
count()
)不是固定的,而且变量的数量可以从 1 到 1 不等。它们将作为参数传递给更广泛的函数。因此,我正在寻找一种可以与
curly-curly
或类似的解决方案很好地配合的解决方案。变量的名称没有任何模式。

我已经考虑过多次调用

tidyr::pivot_longer()
,但我无法弄清楚这如何处理不同数量的变量。

我认为更好的方法可能是将

dplyr::across()
dplyr::cur_column()
一起使用。类似于下面的伪代码:

var_count <- function(cnt_var) {
  mtcars %>%
    count(across({{ cnt_var }})) %>% # this works as intended
    mutate(across({{ cnt_var }}, \(col) cur_column(), .names = "category")) %>% # an attempt to create the 'variable' names. doesn't work when length(cnt_var) > 1
    rename_with(.cols = {{ cnt_var }}, .fn = "category") # a thought about how to create the 'category' columns
}

var_count(cnt_var = c(cyl)) # this ideally should produce one name-value pair: variable1 and category1

var_count(cnt_var = c(cyl, gear)) # this should produce two pairs: variable1, category1, variable2, category2

var_count(cnt_var = c(cyl, gear, vs)) # this should produce three pairs, etc

我理想地想要一个

tidyverse
解决方案,但欢迎所有建议。谢谢各位!

r dplyr tidyr
1个回答
0
投票

正如您已经猜到的那样,我会选择

across
cur_column
和一些重命名。第一步,我创建
category
variable
列,然后删除原始列。之后我使用
rename_with
string::str_replace
将列名后缀替换为数字后缀:

library(dplyr, warn = FALSE)
library(stringr)

mtcars %>%
  count(cyl, gear) |>
  mutate(
    across(-n, list(
      variable = ~ cur_column(),
      category = ~.x
    ),
    .names = "{.fn}_{.col}"
    )
  ) |>
  select(matches("^(category|variable)"), n) |>
  rename_with(
    ~ stringr::str_replace(.x, "_.*$", \(x) as.numeric(factor(x))),
    .cols = -n
  )
#>   variable1 category1 variable2 category2  n
#> 1       cyl         4      gear         3  1
#> 2       cyl         4      gear         4  8
#> 3       cyl         4      gear         5  2
#> 4       cyl         6      gear         3  2
#> 5       cyl         6      gear         4  4
#> 6       cyl         6      gear         5  1
#> 7       cyl         8      gear         3 12
#> 8       cyl         8      gear         5  2

var_count <- function(.data, ...) {
  .data |> 
    count(...) |>
    mutate(
      across(-n, list(
        variable = ~ cur_column(),
        category = ~.x
      ),
      .names = "{.fn}_{.col}"
      )
    ) |>
    select(matches("^(category|variable)"), n) |>
    rename_with(
      ~ stringr::str_replace(.x, "_.*$", \(x) as.numeric(factor(x))),
      .cols = -n
    )
}

var_count(mtcars, cyl)
#>   variable1 category1  n
#> 1       cyl         4 11
#> 2       cyl         6  7
#> 3       cyl         8 14

var_count(mtcars, cyl, gear)
#>   variable1 category1 variable2 category2  n
#> 1       cyl         4      gear         3  1
#> 2       cyl         4      gear         4  8
#> 3       cyl         4      gear         5  2
#> 4       cyl         6      gear         3  2
#> 5       cyl         6      gear         4  4
#> 6       cyl         6      gear         5  1
#> 7       cyl         8      gear         3 12
#> 8       cyl         8      gear         5  2

var_count(mtcars, cyl, gear, vs)
#>    variable1 category1 variable2 category2 variable3 category3  n
#> 1        cyl         4      gear         3        vs         1  1
#> 2        cyl         4      gear         4        vs         1  8
#> 3        cyl         4      gear         5        vs         0  1
#> 4        cyl         4      gear         5        vs         1  1
#> 5        cyl         6      gear         3        vs         1  2
#> 6        cyl         6      gear         4        vs         0  2
#> 7        cyl         6      gear         4        vs         1  2
#> 8        cyl         6      gear         5        vs         0  1
#> 9        cyl         8      gear         3        vs         0 12
#> 10       cyl         8      gear         5        vs         0  2
© www.soinside.com 2019 - 2024. All rights reserved.