是否有办法将多个调用传递给pivot_longger中的names_sep或names_patterns

0h4hbjxa  于 2023-01-06  发布在  其他
关注(0)|答案(3)|浏览(111)

我有一个相当大的数据集,我想把它转换成一个更长的 Dataframe 。我想使用names_sep或names_pattern来传递多个调用。
我在下面提供了一个复制版本,然而,真实的数据集要大得多,大约有30个国家,最终整个数据集有大约7000列(即变量)。
这是我的复制版本:

au <- tribble(
  ~ expert, ~ leftright_au_spo, ~ immigration_au_spo, ~ leftright_au_ovp, ~ immigration_au_ovp,
  1, 3, 4, 5, 6,  
  2, 3, 4, 5, 6,   
  3, 3, 4, 5, 6
)

nl <- tribble(
  ~ expert, ~ leftright_nl_pvda, ~ immigration_nl_pvda, ~ leftright_nl_vvd, ~ immigration_nl_vvd,
  4, 3, 4, 5, 6,  
  5, 3, 4, 5, 6, 
  6, 3, 4, 5, 6
)

使用头:

> head(au)
# A tibble: 3 x 5
  expert leftright_au_spo immigration_au_spo leftright_au_ovp immigration_au_ovp
   <dbl>            <dbl>              <dbl>            <dbl>              <dbl>
1      1                3                  4                5                  6
2      2                3                  4                5                  6
3      3                3                  4                5                  6

> head(nl)
# A tibble: 3 x 5
  expert leftright_nl_pvda immigration_nl_pvda leftright_nl_vvd immigration_nl_vvd
   <dbl>             <dbl>               <dbl>            <dbl>              <dbl>
1      4                 3                   4                5                  6
2      5                 3                   4                5                  6
3      6                 3                   4                5                  6

更广泛的数据形式有一个变量,分别代表一个问题、一个国家(以 * x * 分隔)和一个政党。移民局
如果我这样做,我会在更长的 Dataframe 中得到我想要的。我会在每个问题上得到一个Maven。

austria_longer <- au %>% 
  pivot_longer(
    !expert, 
    names_to = c(".value", "party"), 
    names_sep = "_au_",
    names_transform = list(party = as.factor)) 

netherlands_longer <- nl %>% 
  pivot_longer(
    !expert, 
    names_to = c(".value", "party"), 
    names_sep = "_nl_",
    names_transform = list(party = as.factor))

这产生:

> head(austria_long)
# A tibble: 6 x 4
  expert party leftright immigration
   <dbl> <fct>     <dbl>       <dbl>
1      1 spo           3           4
2      1 ovp           5           6
3      2 spo           3           4
4      2 ovp           5           6
5      3 spo           3           4
6      3 ovp           5           6

以及:

> head(netherlands_long)
# A tibble: 6 x 4
  expert party leftright immigration
   <dbl> <fct>     <dbl>       <dbl>
1      4 pvda          3           4
2      4 vvd           5           6
3      5 pvda          3           4
4      5 vvd           5           6
5      6 pvda          3           4
6      6 vvd           5           6

然后,我将它们合并成一个数据集。这正是我想要的。但这相当耗费人力:

df_combined <- sjmisc::add_rows(austria_longer,
                                netherlands_longer,
                                id = "country")

> head(df_combined, n = 30)
# A tibble: 12 x 5
   country expert party leftright immigration
   <chr>    <dbl> <fct>     <dbl>       <dbl>
 1 1            1 spo           3           4
 2 1            1 ovp           5           6
 3 1            2 spo           3           4
 4 1            2 ovp           5           6
 5 1            3 spo           3           4
 6 1            3 ovp           5           6
 7 2            4 pvda          3           4
 8 2            4 vvd           5           6
 9 2            5 pvda          3           4
10 2            5 vvd           5           6
11 2            6 pvda          3           4
12 2            6 vvd           5           6

不过,我的问题是:如果我将数据集作为列表导入并生成单个 Dataframe ,是否有办法使用names_sep或names_pattern来完成上述操作,为每个Maven生成一个更长的版本,为party添加一个新列,为每个问题(即leftright,immigration)添加一个单独的变量(column)?问题是我需要为每个国家设置一个唯一的指示符(* here *)。
我还不知道如何传递多个对names_sep的调用,或者使用names_pattern生成语法来解决这个问题。

fulldataset_longer <- fulldataset %>% # fulldataset in this case would be both au and nl
  pivot_longer(
    !expert, 
    names_to = c(".value", "party"), 
    names_sep = "_somethinghere_",
    names_transform = list(party = as.factor))

换句话说,我是否可以为names_sep提供一个列表或向量,例如:"* au "," nl *".....或者有没有办法用names_pattern来解决这个问题。我还不能弄清楚是否有可能将多个调用传递给names_sep或names_pattern。

cx6n0qe3

cx6n0qe31#

使用names_pattern参数和自定义函数,您可以执行以下操作:

library(tidyr)
library(purrr)

to_long <- function(x) {
  x %>% 
    pivot_longer(
      !expert, 
      names_to = c(".value", "country", "party"), 
      names_pattern = "(.*)_(.*)_(.*)",
      names_transform = list(party = as.factor)) 
}

list(au, nl) |> 
  purrr::map_df(to_long)
#> # A tibble: 12 × 5
#>    expert country party leftright immigration
#>     <dbl> <chr>   <fct>     <dbl>       <dbl>
#>  1      1 au      spo           3           4
#>  2      1 au      ovp           5           6
#>  3      2 au      spo           3           4
#>  4      2 au      ovp           5           6
#>  5      3 au      spo           3           4
#>  6      3 au      ovp           5           6
#>  7      4 nl      pvda          3           4
#>  8      4 nl      vvd           5           6
#>  9      5 nl      pvda          3           4
#> 10      5 nl      vvd           5           6
#> 11      6 nl      pvda          3           4
#> 12      6 nl      vvd           5           6
vmdwslir

vmdwslir2#

将数据保留在list中,并使用names_pattern代替names_sep

library(dplyr)
library(tidyr)
library(purrr)
lst(au, nl) %>% 
  map(~ .x %>% 
  pivot_longer(cols = -expert, names_to = c(".value", "party"), 
   names_pattern = "^([^_]+)_\\w+_(\\w+)",
    names_transform = list(party = as.factor))) %>%
  list_rbind(names_to = "Country")
  • 输出
# A tibble: 12 × 5
   Country expert party leftright immigration
   <chr>    <dbl> <fct>     <dbl>       <dbl>
 1 au           1 spo           3           4
 2 au           1 ovp           5           6
 3 au           2 spo           3           4
 4 au           2 ovp           5           6
 5 au           3 spo           3           4
 6 au           3 ovp           5           6
 7 nl           4 pvda          3           4
 8 nl           4 vvd           5           6
 9 nl           5 pvda          3           4
10 nl           5 vvd           5           6
11 nl           6 pvda          3           4
12 nl           6 vvd           5           6

或者通过从命名列表中提取name来使用names_sep

library(stringr)
lst(au, nl) %>% 
   imap(~ .x %>%
   pivot_longer(cols = -expert, names_to = c(".value", "party"), 
     names_sep = str_c('_', .y, '_'),
   names_transform = list(party = as.factor))) %>%
   list_rbind(names_to = "Country")
  • 输出
# A tibble: 12 × 5
   Country expert party leftright immigration
   <chr>    <dbl> <fct>     <dbl>       <dbl>
 1 au           1 spo           3           4
 2 au           1 ovp           5           6
 3 au           2 spo           3           4
 4 au           2 ovp           5           6
 5 au           3 spo           3           4
 6 au           3 ovp           5           6
 7 nl           4 pvda          3           4
 8 nl           4 vvd           5           6
 9 nl           5 pvda          3           4
10 nl           5 vvd           5           6
11 nl           6 pvda          3           4
12 nl           6 vvd           5           6
gjmwrych

gjmwrych3#

这里有一个不同的方法:

library(dplyr)
library(tidyr)

bind_rows(au, nl) %>% 
  pivot_longer(-expert, names_to = "name", values_to = "leftright",  values_drop_na = TRUE) %>% 
  separate(name, into=c("left_right", "Country", "party")) %>% 
  mutate(immigration = lead(leftright, default = last(leftright))) %>% 
  filter(row_number() %% 2 == 1) %>% 
  select(Country, expert, party, leftright, immigration)
Country expert party leftright immigration
   <chr>    <dbl> <chr>     <dbl>       <dbl>
 1 au           1 spo           3           4
 2 au           1 ovp           5           6
 3 au           2 spo           3           4
 4 au           2 ovp           5           6
 5 au           3 spo           3           4
 6 au           3 ovp           5           6
 7 nl           4 pvda          3           4
 8 nl           4 vvd           5           6
 9 nl           5 pvda          3           4
10 nl           5 vvd           5           6
11 nl           6 pvda          3           4
12 nl           6 vvd           5           6

相关问题