#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