Может ли функция map заменить исходный фрейм данных?

#r #dplyr #purrr

#r #dplyr #муррр

Вопрос:

У меня есть три переменные RR1234, RR5678, RR0135:

 RR1234   <- rnorm(100, 2, 3)
RR5678    <-  rnorm(100,3,4)
RR0135    <- rnorm(100,4,5)  
x   <- data.frame(RR1234,RR5678,RR0135)
  

У меня есть функция для обрезки x :

 done   <- function(x){
   x[x > 1] = NA
   return(x)
}
  

Я хочу обрезать RR1234 и RR5678 :

 c(x$RR1234,x$RR5678) %>% map(done)
  

но данные в x нем остаются прежними.

Я также пытался:

 x   <-  x %>%  select(RR1234,RR5678) %>% map(done)
  

Хотя первые две переменные работают хорошо, но третья RR0135 исчезла.

Есть ли какой-либо удобный способ заменить две переменные в x ?

Ответ №1:

Давайте рассмотрим то, что вы пробовали:

 c(x$RR1234,x$RR5678) %>% map(done)
  

Это выполняет операцию x , но не изменяет содержимое x . Содержимое x не изменится, если вы не назначите операцию обратно x .

 x   <-  x %>%  select(RR1234,RR5678) %>% map(done)
  

Эта строка кода меняется x , но select глагол from dplyr означает, что вы включаете только эти два столбца. Другие столбцы были исключены из операции. Если вы хотите изменить эти два столбца, а не третий, вы можете это сделать. Есть два способа. Ни один из них не используется map() .

 # Generate the data using set.seed to make it reproducible
set.seed(1)
RR1234   <- rnorm(100, 2, 3)
RR5678    <-  rnorm(100,3,4)
RR0135    <- rnorm(100,4,5)  
x   <- data.frame(RR1234,RR5678,RR0135)
  

Используя базовую функциональность R, вы можете присвоить новые значения столбцам data.frame, используя $ подмножество to, не изменяя ничего другого. Это работает с любым другим типом подмножества.

 # base R
x$RR1234 <- done(x$RR1234)
x$RR5678 <- done(x$RR5678)
  

Используя dplyr версию 1.0 или выше, вы можете использовать следующее. mutate(across(...)) Конструкция позволяет изменять несколько столбцов на основе критериев передачи и функций across .

 x %>% mutate(across(c("RR1234", "RR5678"), done))
  

Ответ №2:

Я бы посоветовал вам использовать across() from dplyr . И поскольку вы хотите преобразовать некоторые переменные, лучше использовать mutate() . Здесь код:

 library(dplyr)
#Data
RR1234   <- rnorm(100, 2, 3)
RR5678    <-  rnorm(100,3,4)
RR0135    <- rnorm(100,4,5)  
x   <- data.frame(RR1234,RR5678,RR0135)
#Function
done   <- function(x){
  x[x > 1] = NA
  return(x)
}
#Code
x2 <- x %>%  mutate(across(RR1234:RR5678,~done(.)))
  

Вывод:

          RR1234     RR5678      RR0135
1    0.94194089         NA  13.0713017
2   -0.33647069 -2.3019341   9.4639157
3            NA -0.5368949  -6.4242588
4            NA         NA   4.4593853
5            NA         NA   0.6853094
6            NA         NA   7.6834331
7            NA         NA   1.8147963
8   -0.41588192         NA   9.3598014
9    0.76115066         NA  10.8331170
10           NA         NA   4.7973967
11           NA -2.3059266  -7.7575549
12           NA         NA   1.8152209
13           NA         NA  -0.9860351
14           NA         NA  12.1584945
15  -2.24455694  0.6763838  -4.2775746
16           NA         NA  -0.4178979
17           NA         NA  11.2213595
18           NA         NA  -2.2960382
19           NA         NA   0.3525616
20           NA -2.0038667   2.9802946
21           NA  0.7472525   4.0493003
22           NA         NA  13.6511832
23           NA         NA   6.5547820
24           NA -2.2045896   1.2317368
25  -0.62548661 -0.8736796   0.5770349
26           NA  0.4075356   9.2716612
27           NA         NA   4.1747139
28           NA         NA  -7.3872696
29   0.94287484 -8.0979632   0.5209943
30           NA -3.9503837   4.1438962
31  -2.74859617         NA   4.0467313
32           NA         NA   9.4205472
33           NA         NA -10.1071739
34           NA         NA  13.7521859
35  -1.15968127         NA  -4.0899815
36           NA         NA   7.7387901
37  -2.45832478         NA  -5.6710160
38  -3.09780799 -2.4786657  -4.1983864
39           NA         NA   8.0691432
40   0.44259503         NA  -2.4539690
41           NA         NA  -4.2937684
42           NA         NA  -3.4187835
43  -1.67688948         NA   5.2468200
44           NA  0.1528275  -6.1676265
45           NA         NA   6.5787688
46           NA         NA   1.2673593
47  -5.77722184         NA   6.7476928
48  -0.71438036 -0.6985110   1.1490648
49  -2.69295812         NA   2.7580518
50           NA         NA   6.7804525
51           NA         NA  -1.0621607
52           NA         NA   3.7175144
53           NA         NA   6.3843942
54           NA         NA   8.3657269
55  -1.46609589         NA  -2.5650315
56           NA -9.7247597  -1.0451021
57           NA         NA  11.2932211
58  -0.38620085         NA   6.5005979
59           NA         NA   2.5991516
60  -0.63715413         NA   2.9463852
61   0.12413129 -0.2764512  13.8596677
62           NA -3.5446673  -0.5171467
63           NA         NA   3.9371540
64  -0.31371041         NA   8.9294396
65  -1.18244591         NA   8.4827556
66  -4.83866907         NA   3.9618274
67           NA         NA  10.1643994
68  -0.75624474         NA  -3.2039191
69  -3.62029427         NA  -1.8827352
70           NA         NA   3.3186486
71           NA -2.9736113   4.0444030
72           NA         NA   5.6982921
73  -1.35997829  0.9391924   4.2699128
74  -3.48608075         NA  -2.0635431
75  -6.89075863 -5.9582709   0.4530760
76           NA  0.2738838  -3.4495561
77  -4.11640879 -1.6386795   8.9934335
78  -4.49512380         NA  -4.5578025
79  -2.66125238 -2.1222533   1.7672672
80           NA  0.3992611   1.6496420
81           NA         NA  -4.8627943
82  -0.41373126 -3.4452060  -2.9630815
83  -1.74671667         NA   2.0555012
84  -0.58334242         NA   6.2798613
85           NA         NA   2.1313488
86           NA         NA  15.9778175
87  -1.08969338         NA  -5.5826951
88           NA -2.4728756   4.6548008
89           NA -5.0936805  10.6863344
90           NA         NA   6.3066017
91           NA         NA   3.7410041
92           NA         NA  -4.8135729
93           NA         NA   9.3064735
94  -0.04695171         NA   4.4903433
95           NA         NA  11.7926356
96           NA         NA   4.7113170
97  -4.08935228         NA   7.9562516
98           NA         NA  13.9372643
99           NA         NA   1.6008497
100          NA         NA   5.4534442
  

Комментарии:

1. Один дополнительный вариант: done() может быть выполнен встроенным с if_else() : mutate(x, across(c("RR1234", "RR5678"), ~if_else(. > 1, NA_real_, .)))

Ответ №3:

Я удивлен, что вы используете purrr::map и канал magrittr / %>% tidyverse, но не знакомы с dplyr::mutate ним, поскольку два пакета обычно преподаются вместе, причем dplyr сначала преподаются.

 dplyr::mutate(x, across(c(RR1234, RR5678), done))
  

Ответ №4:

Я согласен, что mutate / across — лучшая идиома здесь. Учитывая, о чем конкретно спрашивал OP purrr::map , вот map решение:

 set.seed(123)

as.list(colnames(x)) %>%
  setNames(colnames(x)) %>%
  map_dfc(function(col) if_else(x[col] > 1, NA_real_, pull(x[col])))
  

Вывод:

 # A tibble: 100 x 3
    RR1234 RR5678  RR0135
     <dbl>  <dbl>   <dbl>
 1  0.319   0.158 NA     
 2 NA      NA     NA     
 3 NA      NA     NA     
 4 NA      NA     NA     
 5 NA      -0.806 NA     
 6 NA      NA     NA     
 7 NA      -0.140  0.0570
 8 -1.80   -3.67  NA     
 9 -0.0606 NA     NA     
10  0.663  NA     NA     
# … with 90 more rows