簡體   English   中英

跨多個列變異以創建新的變量集

[英]Mutate across multiple columns to create new variable sets

我有一個國家和年份級別的面板數據集,我想根據現有變量創建兩個新變量。

國家 變量1 變量2 變量3 變量 4 mean_var1 relmean_var1
1910 GER 1 4 10 6 3 0.333
1911 GER 2 3 11 7 1.5 1.3333
1910 法蘭克福機場 5 6 8 9 3 1.66667
1911 法蘭克福機場 1 4 10 9 1.5 .66667

我想做的是創建兩個新變量集:(1)每年(跨國家)平均值的變量集和(2)相對於年平均值的國家價值變量集。 例如,對於 var1(1) 將產生 mean_var1 和 (2) relmean_var1 並且我希望這些用於所有其他變量。 數據集中總共有 1000 多個變量,但我只會將此 function 應用於大約 6 個。

我有適用於第一部分的代碼,但我想盡可能有效地將它與第二部分結合起來。

library(dplyr)
library(purrr)
df<- df%>% 
            group_by(year) %>%
            mutate_at(.funs = list(mean = ~mean(.)), .vars = c("var1", "var1", "var1", "var4"))

此代碼產生名為 var1_mean 的新變量(我更喜歡 mean_var1:如何更改此名稱?)

對於第二步,我嘗試過:

df <- df %>%
map2_dfr(.x = d.test %>%
            select(var1, var2),
          .y = d.test %>%
            select(var1_mean, var2_mean), 
          ~ .x / .y) %>%
   setNames(c("relmean_var1", "relmean_var2"))

我得到錯誤

“”選擇錯誤(., var1, var2):未找到 object 'd.test'。”

. (我從這個問題中得到了這個設置)

我也試過:

 map2(var1, var1_mean, ~ df[[.x]] / df[[.y]]) %>% 
   set_names(cols) %>% 
   bind_cols(df, .)

並得到

“map2 中的錯誤(var1,var1_mean,~df[[.x]]/df[[.y]]):未找到 object 'var1'

結合這兩個目標的最佳方式是什么? 理想情況下,命名方案 mean_var1 用於 (1),relmean_var1 用於 (2)

編輯:輸入 dataframe 應該如下所示:

data <- tibble::tribble(
  ~year, ~country, ~var1, ~var2, ~var3, ~var.4,
  1910L,    "GER",    1L,    4L,   10L,     6L,
  1911L,    "GER",    2L,    3L,   11L,     7L,
  1910L,    "FRA",    5L,    6L,    8L,     9L,
  1911L,    "FRA",    1L,    4L,   10L,     9L
)

output dataframe 應如下所示(對於所有變量,僅以 var1 為例,但 var2 到 var4 的格式應相同):

datanew  <- tibble::tribble(
  ~year, ~country, ~var1, ~var2, ~var3, ~var.4, ~mean_var1 , ~relmean_var1
  1910L,    "GER",    1L,    4L,   10L,     6L,     3L,        .3333L,
  1911L,    "GER",    2L,    3L,   11L,     7L,     1.5L,     1.3333L,
  1910L,    "FRA",    5L,    6L,    8L,     9L,     3L,       1.6667L,
  1911L,    "FRA",    1L,    4L,   10L,     9L      1.5L,      .6667L,
)

這在長格式中可能更容易,但這是一個您可以追求寬數據的選項。

使用最新版本across dplyr ,您可以.names mutate來定義您希望新列的外觀。

library(tidyverse)

my_col <- c("var1", "var2", "var3", "var4")

df %>%
  group_by(year) %>%
  mutate(across(my_col, mean, .names = "mean_{col}")) %>%
  mutate(across(my_col, .names = "relmean_{col}") / across(paste0("mean_", my_col)))

Output

   year country  var1  var2  var3  var4 mean_var1 mean_var2 mean_var3 mean_var4 relmean_var1 relmean_var2 relmean_var3 relmean_var4
  <int> <chr>   <int> <int> <int> <int>     <dbl>     <dbl>     <dbl>     <dbl>        <dbl>        <dbl>        <dbl>        <dbl>
1  1910 GER         1     4    10     6       3         5         9         7.5        0.333        0.8          1.11         0.8  
2  1911 GER         2     3    11     7       1.5       3.5      10.5       8          1.33         0.857        1.05         0.875
3  1910 FRA         5     6     8     9       3         5         9         7.5        1.67         1.2          0.889        1.2  
4  1911 FRA         1     4    10     9       1.5       3.5      10.5       8          0.667        1.14         0.952        1.12
library(tidyverse)

data <- tibble::tribble(
  ~year, ~country, ~var1, ~var2, ~var3, ~var.4,
  1910L,    "GER",    1L,    2L,   10L,     6L,
  1911L,    "GER",    2L,    3L,   11L,     7L,
  1910L,    "FRA",    5L,    6L,    8L,     9L,
  1911L,    "FRA",    1L,    3L,   10L,     9L
)

data_long <-
  data %>%
  pivot_longer(-c(year, country))

data_long
#> # A tibble: 16 x 4
#>     year country name  value
#>    <int> <chr>   <chr> <int>
#>  1  1910 GER     var1      1
#>  2  1910 GER     var2      2
#>  3  1910 GER     var3     10
#>  4  1910 GER     var.4     6
#>  5  1911 GER     var1      2
#>  6  1911 GER     var2      3
#>  7  1911 GER     var3     11
#>  8  1911 GER     var.4     7
#>  9  1910 FRA     var1      5
#> 10  1910 FRA     var2      6
#> 11  1910 FRA     var3      8
#> 12  1910 FRA     var.4     9
#> 13  1911 FRA     var1      1
#> 14  1911 FRA     var2      3
#> 15  1911 FRA     var3     10
#> 16  1911 FRA     var.4     9

means_country <-
  data_long %>%
  group_by(country) %>%
  summarise(mean_country_value = mean(value))

means_years <-
  data_long %>%
  group_by(year) %>%
  summarise(mean_year_value = mean(value))

data %>%
  left_join(means_country) %>%
  left_join(means_years)
#> Joining, by = "country"
#> Joining, by = "year"
#> # A tibble: 4 x 8
#>    year country  var1  var2  var3 var.4 mean_country_value mean_year_value
#>   <int> <chr>   <int> <int> <int> <int>              <dbl>           <dbl>
#> 1  1910 GER         1     2    10     6               5.25            5.88
#> 2  1911 GER         2     3    11     7               5.25            5.75
#> 3  1910 FRA         5     6     8     9               6.38            5.88
#> 4  1911 FRA         1     3    10     9               6.38            5.75

代表 package (v2.0.1) 於 2021 年 11 月 24 日創建

這是@danlooo 方法的擴展,因此國家級平均值和年份平均值位於同一數據集中(如果需要)。 顯着的區別是在 pipe 鏈中使用兩個mutate s,而不是兩個summarize s,然后加入。

考慮一下你是否真的想要它再次變寬。 通常保持較長時間更容易(例如,刪除對tidyr::pivot_wider()的最終調用)。

ds <- tibble::tribble(
  ~year, ~country, ~var1, ~var2, ~var3,  ~var4,
  1910L,    "GER",    1L,    4L,   10L,     6L,
  1911L,    "GER",    2L,    3L,   11L,     7L,
  1910L,    "FRA",    5L,    6L,    8L,     9L,
  1911L,    "FRA",    1L,    4L,   10L,     9L
)  

ds |> 
  dplyr::mutate(
    year = as.character(year)   # To help the pivot below
  ) |> 
  tidyr::pivot_longer(
    cols         = -c(year, country), 
    names_to     = "key",
    names_prefix = "^var"
  ) |> 
  dplyr::group_by(country, key) |> 
  dplyr::mutate(
    m_c   = mean(value),  # Mean for the Country (and variable)
    r_c   = value / m_c,  # Relative mean for the Country (and variable)
  ) |> 
  dplyr::ungroup() |> 
  dplyr::group_by(year, key) |> 
  dplyr::mutate(
    m_y   = mean(value),  # Mean for the Year (and variable)
    r_y   = value / m_y,  # Relative mean for the Year (and variable)
  ) |> 
  dplyr::ungroup() |> 
  dplyr::mutate(
    year  = as.integer(year)  # Return it to a number
  ) |> 
  tidyr::pivot_wider(
    id_cols = c(year, country),
    names_from = key,
    names_glue = "{.value}_{key}",
    values_from = c(value, m_c, r_c, m_y, r_y)
  )

Output(寬)我更喜歡像@danlooo這樣更長的描述性變量名稱,但我希望一切都適合SO屏幕

   year country value_1 value_2 value_3 value_4 m_c_1 m_c_2 m_c_3 m_c_4 r_c_1 r_c_2 r_c_3 r_c_4 m_y_1 m_y_2 m_y_3 m_y_4 r_y_1 r_y_2 r_y_3 r_y_4
  <int> <chr>     <int>   <int>   <int>   <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1  1910 GER           1       4      10       6   1.5   3.5  10.5   6.5 0.667 1.14  0.952 0.923   3     5     9     7.5 0.333 0.8   1.11  0.8  
2  1911 GER           2       3      11       7   1.5   3.5  10.5   6.5 1.33  0.857 1.05  1.08    1.5   3.5  10.5   8   1.33  0.857 1.05  0.875
3  1910 FRA           5       6       8       9   3     5     9     9   1.67  1.2   0.889 1       3     5     9     7.5 1.67  1.2   0.889 1.2  
4  1911 FRA           1       4      10       9   3     5     9     9   0.333 0.8   1.11  1       1.5   3.5  10.5   8   0.667 1.14  0.952 1.12 

Output (長 -- 沒有最后的tidyr::pivot_wider()

# A tibble: 16 x 8
    year country key   value   m_c   r_c   m_y   r_y
   <int> <chr>   <chr> <int> <dbl> <dbl> <dbl> <dbl>
 1  1910 GER     1         1   1.5 0.667   3   0.333
 2  1910 GER     2         4   3.5 1.14    5   0.8  
 3  1910 GER     3        10  10.5 0.952   9   1.11 
 ...
15  1911 FRA     3        10   9   1.11   10.5 0.952
16  1911 FRA     4         9   9   1       8   1.12 

暫無
暫無

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

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