मेरे पास लगातार नामित कॉलम वाला डेटासेट है और मैं उनके समूह द्वारा कॉलम का औसत लेना चाहता हूं जैसे,

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 पैटर्न का पालन करें जैसा कि ऊपर दिए गए उदाहरण में है।

2
John-Henry 8 नवम्बर 2020, 19:37

3 जवाब

सबसे बढ़िया उत्तर

अपडेट करें यहां एक साफ तरीका दिया गया है जिसके लिए rename या bind_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
1
andrew_reece 8 नवम्बर 2020, 23:00

यहाँ एक समाधान है:

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_ को डुप्लिकेट करता है), और दूसरा जो देता है नाम जो आप चाहते हैं लेकिन प्रति समूह कॉलम की संख्या पहले से जानना आवश्यक है।

1
Joao Pedro Macalos 8 नवम्बर 2020, 20:34

हम कॉलम नाम पैटर्न के आधार पर डेटा को list डेटासेट में विभाजित करने के लिए split.default का उपयोग कर सकते हैं, फिर 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
1
akrun 9 नवम्बर 2020, 00:36