R, dplyr, альтернативы циклическим операциям над столбцами - PullRequest
0 голосов
/ 23 октября 2019

Предположим, у меня есть фрейм данных со многими столбцами, которые можно сопоставить в пары.

Например,

df  = tibble(x = rnorm(1000), y = rnorm(1000))

create_many_columns <- function(df, n) {
  varname1 <- paste("x", n , sep=".")
  varname2 <- paste("y", n , sep=".")
  df %>% 
    mutate(!!varname1 := x * n) %>%
    mutate(!!varname2 := y * n)
}

df

Понятно, что мы можем сопоставлять столбцы (x.n и y.n).

# A tibble: 1,000 x 22
        x       y    x.2     y.2   x.3     y.3   x.4    y.4   x.5    y.5   x.6     y.6    x.7     y.7    x.8     y.8
    <dbl>   <dbl>  <dbl>   <dbl> <dbl>   <dbl> <dbl>  <dbl> <dbl>  <dbl> <dbl>   <dbl>  <dbl>   <dbl>  <dbl>   <dbl>
 1 -1.57   0.597  -3.14   1.19   -4.71  1.79   -6.28  2.39  -7.85  2.99  -9.42   3.58  -11.0    4.18  -12.6    4.78 
 2 -1.20   1.02   -2.40   2.03   -3.60  3.05   -4.80  4.06  -6.00  5.08  -7.20   6.10   -8.40   7.11   -9.60   8.13 
 3  1.16  -0.304   2.32  -0.609   3.47 -0.913   4.63 -1.22   5.79 -1.52   6.95  -1.83    8.10  -2.13    9.26  -2.44 
 4  0.870 -1.73    1.74  -3.45    2.61 -5.18    3.48 -6.90   4.35 -8.63   5.22 -10.4     6.09 -12.1     6.96 -13.8  
 5  0.621  1.89    1.24   3.78    1.86  5.68    2.48  7.57   3.11  9.46   3.73  11.4     4.35  13.2     4.97  15.1  
 6 -0.970  0.347  -1.94   0.694  -2.91  1.04   -3.88  1.39  -4.85  1.74  -5.82   2.08   -6.79   2.43   -7.76   2.78 
 7  0.453  0.0866  0.906  0.173   1.36  0.260   1.81  0.346  2.26  0.433  2.72   0.520   3.17   0.606   3.62   0.693
 8 -0.840 -0.956  -1.68  -1.91   -2.52 -2.87   -3.36 -3.82  -4.20 -4.78  -5.04  -5.73   -5.88  -6.69   -6.72  -7.64 
 9 -0.938 -0.967  -1.88  -1.93   -2.81 -2.90   -3.75 -3.87  -4.69 -4.83  -5.63  -5.80   -6.57  -6.77   -7.51  -7.73 
10 -0.551  0.0267 -1.10   0.0535 -1.65  0.0802 -2.21  0.107 -2.76  0.134 -3.31   0.160  -3.86   0.187  -4.41   0.214
# … with 990 more rows, and 6 more variables: x.9 <dbl>, y.9 <dbl>, x.10 <dbl>, y.10 <dbl>, x.11 <dbl>, y.11 <dbl>

Я хочу получить последовательность столбцов, которая будет произведением соответствующих столбцов. Например,

for(i in 2:11){
  df[[paste0("z.", i)]] = df[[paste0("x.", i)]] * df[[paste0("y.", i)]]
}

df %>% select(contains("z"))
# A tibble: 1,000 x 10
       z.2     z.3    z.4    z.5     z.6     z.7     z.8     z.9    z.10    z.11
     <dbl>   <dbl>  <dbl>  <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
 1 -1.44   -3.25   -5.78  -9.02  -13.0   -17.7   -23.1   -29.2   -36.1   -43.7  
 2  0.865   1.95    3.46   5.41    7.79   10.6    13.8    17.5    21.6    26.2  
 3  0.972   2.19    3.89   6.07    8.75   11.9    15.6    19.7    24.3    29.4  
 4  3.54    7.96   14.2   22.1    31.9    43.4    56.6    71.7    88.5   107.   
 5 -0.298  -0.671  -1.19  -1.86   -2.68   -3.65   -4.77   -6.04   -7.45   -9.02 
 6  4.10    9.22   16.4   25.6    36.9    50.2    65.5    82.9   102.    124.   
 7  3.61    8.12   14.4   22.6    32.5    44.2    57.8    73.1    90.2   109.   
 8 -1.17   -2.64   -4.69  -7.33  -10.5   -14.4   -18.8   -23.7   -29.3   -35.5  
 9  1.52    3.42    6.08   9.50   13.7    18.6    24.3    30.8    38.0    46.0  
10 -0.0328 -0.0738 -0.131 -0.205  -0.295  -0.402  -0.525  -0.665  -0.820  -0.993
# … with 990 more rows

Это решение хорошо, если мне не нужно перегружать мой код циклами. Но я делаю, так как я должен регулярно применять этот тип преобразований. Есть ли варианты, чтобы написать его более экономно?

Например, если бы я хотел получить показатель степени всех элементов столбцов "x", я мог бы сделать

 df %>%
  mutate_at(vars(contains("x")), exp )

вместо того, чтобы писать цикл вроде

for(i in 2:11){
  df[[paste0("x.", i)]] = exp(df[[paste0("x.", i)]] )
}

Для начального примера, я бы ожидал, что есть возможность написать что-то вроде

df %>% mutate(z.n = x.n * y.n, n = 2:11)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...