簡體   English   中英

使用`map`按列名查找rowMeans

[英]Using `map` to find rowMeans by column names

我有一個具有一致命名列的數據集,我想按他們的組取列的平均值,例如,

library(dplyr)
library(purrr)
library(glue)

df <- tibble(`1_x_blind` = 1:3, 
       `1_y_blind` = 7:9,
       `2_x_blind` = 4:6, 
       `2_y_blind` = 5:7)
  
df %>% 
  mutate(`1_overall_test` = rowMeans(select(., matches(glue("^1_.*_blind$")))))
#> # A tibble: 3 x 5
#>   `1_x_blind` `1_y_blind` `2_x_blind` `2_y_blind` `1_overall_test`
#>         <int>       <int>       <int>       <int>            <dbl>
#> 1           1           7           4           5                4
#> 2           2           8           5           6                5
#> 3           3           9           6           7                6

這種方法效果很好。 我的下一步是縮放它,以便我可以完成整個系列的列,例如,類似

df %>% 
  mutate(overall_blind = map(1:2, ~rowMeans(select(., matches(glue("^{.x}_.*_blind$"))))))
#> Error: Problem with `mutate()` input `overall_blind`.
#> x no applicable method for 'select' applied to an object of class "c('integer', 'numeric')"
#> ℹ Input `overall_blind` is `map(1:2, ~rowMeans(select(., matches(glue("^{.x}_.*_blind$")))))`.

我認為這里的問題是select混淆了. 操作員。 是否可以以這種方式map一系列列名? 理想情況下,我希望列名遵循{.x}_overall模式,如上例所示。

這是一種解決方案:

map_dfc(1:2, function(x) {
  select(df, matches(glue("^{x}_.*_blind$"))) %>%
    mutate(overall_blind = rowMeans(select(., matches(glue("^{x}_.*_blind$"))))) %>%
    
    # General but not perfect names
    # set_names(paste0(x, "_", names(.)))
    
    # Hand-tailored names
    set_names(c(names(.)[1], names(.)[2], paste0(x, "_", names(.)[3])))
  })

#> # A tibble: 3 x 6
#>   `1_x_blind` `1_y_blind` `1_overall_blind` `2_x_blind` `2_y_blind` `2_overall_blind`
#>         <int>       <int>             <dbl>       <int>       <int>             <dbl>
#> 1           1           7                 4           4           5               4.5
#> 2           2           8                 5           5           6               5.5
#> 3           3           9                 6           6           7               6.5

我添加了兩種為每個組命名overall_blind列的可能性,一個更通用但不完美的名稱(它復制了數據列的1_2_ ),另一個給出了您想要的名稱但需要提前知道數量每組列。

更新這是一種不需要renamebind_cols

map_dfc(1:2, 
        function(x) df %>% 
          select(matches(glue("^{x}_.*_blind$"))) %>%
          mutate("{x}_overall_blind" := rowMeans(.))
        )

# A tibble: 3 x 6
  `1_x_blind` `1_y_blind` `1_overall_blind` `2_x_blind` `2_y_blind` `2_overall_blind`
        <int>       <int>             <dbl>       <int>       <int>             <dbl>
1           1           7                 4           4           5               4.5
2           2           8                 5           5           6               5.5
3           3           9                 6           6           7               6.5

以前的
這是一種map方法。
挑戰在於根據現有列的單獨組對兩個新列進行變異。 最簡單的方法是在它自己的map_dfc()做到這一點,然后將其綁定到現有的df


df %>%
  bind_cols(
    map_dfc(1:2, ~rowMeans(df %>% select(matches(glue("^{.x}_.*_blind$"))))) %>%
      rename_with(~paste0(str_replace(., "\\...", ""), "_overall_blind"))
  )

# A tibble: 3 x 6
  `1_x_blind` `1_y_blind` `2_x_blind` `2_y_blind` `1_overall_blind` `2_overall_blind`
        <int>       <int>       <int>       <int>             <dbl>             <dbl>
1           1           7           4           5                 4               4.5
2           2           8           5           6                 5               5.5
3           3           9           6           7                 6               6.5

這是一種使用樞軸獲得行列組平均值的方法,它避免了正則表達式和mutate / map操作:

df %>%
  mutate(row = row_number()) %>%
  pivot_longer(-row) %>%
  separate(name, c("grp"), sep = "_", extra = "drop") %>%
  group_by(row, grp) %>%
  summarise(overall_blind = mean(value)) %>%
  ungroup() %>%
  pivot_wider(id_cols = row, names_from = grp, values_from = overall_blind, 
              names_glue = "{grp}_{.value}") %>%
  bind_cols(df)

# A tibble: 3 x 6
  `1_overall_blind` `2_overall_blind` `1_x_blind` `1_y_blind` `2_x_blind` `2_y_blind`
              <dbl>             <dbl>       <int>       <int>       <int>       <int>
1                 4               4.5           1           7           4           5
2                 5               5.5           2           8           5           6
3                 6               6.5           3           9           6           7

我們可以使用split.default根據列名模式將數據拆分為數據集list ,然后獲取rowMeans並與原始數據綁定

library(dplyr)
library(purrr)
library(stringr)
df %>%
      split.default(readr::parse_number(names(.))) %>%
      map_dfc(rowMeans) %>% 
      set_names(str_c(names(.), "_overall_blind")) %>%
      bind_cols(df, .)
# A tibble: 3 x 6
#  `1_x_blind` `1_y_blind` `2_x_blind` `2_y_blind` `1_overall_blind` `2_overall_blind`
#        <int>       <int>       <int>       <int>             <dbl>             <dbl>
#1           1           7           4           5                 4               4.5
#2           2           8           5           6                 5               5.5
#3           3           9           6           7                 6               6.5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM