#r #dplyr #key #tibble #rowwise
#r #dplyr #Клавиша #tibble #rowwise
Вопрос:
Есть ли способ создать key
без использования rowwise()
?
Любой указатель очень ценится.
df <- tibble(grp1=rev(LETTERS[1:5]),grp2=letters[11:15],grp3=LETTERS[1:5],
value=rnorm(5,10,10))
df %>% rowwise %>% mutate(key=paste(sort(c(grp1, grp2)), collapse="")) %>% ungroup()
grp1 grp2 grp3 value key
<chr> <chr> <chr> <chr> <chr>
1 E k A -3.73984194875213 AE
2 D l B 3.25846392371014 BD
3 C m C 3.62405652088127 CC
4 B n D 6.41520621902784 BD
5 A o E 20.1892413026407 AE
Обновление: tibble
содержит несколько символьных векторов, но key
должен быть сгенерирован из столбца grp1
и grp3
.
Ответ №1:
используя purrr::pmap_chr
:
library(tidyverse)
df %>% mutate(key=pmap_chr(.[c("grp1","grp3")],~paste(sort(c(...)), collapse="")))
# # A tibble: 5 x 5
# grp1 grp2 grp3 value key
# <chr> <chr> <chr> <chr> <chr>
# 1 E k A 22.0150932758833 AE
# 2 D l B 2.24725610156698 BD
# 3 C m C -6.2414882455089 CC
# 4 B n D 22.5699168856552 BD
# 5 A o E -6.21443670571301 AE
В базе R вы могли бы сделать:
transform(df, key=mapply(function(...) paste(sort(c(...)), collapse=""), grp1, grp3)
Комментарии:
1. Спасибо за ваш ответ! Я обновил свой вопрос… Может ли это сработать, когда у вас есть несколько символьных векторов / столбцов и вам нужно указать, из какого сгенерировать ключ?
2. Пожалуйста, избегайте изменения вопросов таким образом, чтобы ответы устарели, лучше обновить дополнительным примером
3. Прошу прощения за оплошность. Да, ваш ответ решает проблему. Большое спасибо, очень аккуратно!
4. Спасибо @Moody_Mudskipper за обновление обоих ответов. Как оказалось, ответ @AntoniosK быстрее для моих реальных данных (оценивается с помощью
profvis::profvis()
)5. На
df <- as_tibble(cbind(grp1=sample(size=1000,x=rev(LETTERS[1:5]),replace=T),grp2=sample(size=1000,x=letters[11:15],replace=T),grp3=sample(size=1000,x=LETTERS[1:5],replace=T),value=rnorm(1000,10,10)))
аккуратный подход Moody_Mudskipper занимает 30 мс, а аккуратный подход AntoniosK — 10 мс.
Ответ №2:
Вот векторная опция с использованием pmin/pmap
. Возьмите min/max
для каждой строки столбцов ‘grp1’, ‘grp3’ с pmin/pmax
и объедините вместе ( str_c
)
library(dplyr)
library(stringr)
df %>%
mutate(key = str_c(pmin(grp1, grp3), pmax(grp1, grp3)))
# A tibble: 5 x 5
# grp1 grp2 grp3 value key
# <chr> <chr> <chr> <dbl> <chr>
#1 E k A 24.7 AE
#2 D l B 5.66 BD
#3 C m C 16.3 CC
#4 B n D 5.88 BD
#5 A o E -9.22 AE
данные
df <- tibble(grp1=rev(LETTERS[1:5]),grp2=letters[11:15],grp3=LETTERS[1:5],
value=rnorm(5,10,10))
ПРИМЕЧАНИЕ: cbind
преобразуется в matrix
и matrix может содержать только один класс. Преобразование в tibble
с as_tibble
помощью не изменяет класс автоматически. Вместо этого используйте tibble/data.frame
напрямую вместо cbind
маршрута
Комментарии:
1. Потрясающе, это невероятно быстро! Спасибо!
Ответ №3:
Другой способ — использовать mutate
без rowwise
, но с векторизованной версией вашей функции, например, так:
library(dplyr)
# create a function and vectorise it
f = function(x, y) paste(sort(c(x, y)), collapse="")
f = Vectorize(f)
# use the function
df %>% mutate(key = f(grp1, grp3))
# # A tibble: 5 x 5
# grp1 grp2 grp3 value key
# <chr> <chr> <chr> <chr> <chr>
# 1 E k A -4.41213449814982 AE
# 2 D l B 10.4314736952111 BD
# 3 C m C 5.69345098226371 CC
# 4 B n D 4.39266020802413 BD
# 5 A o E 22.0623810028979 AE
Комментарии:
1. Спасибо! Очень аккуратно!
2. @AntoniosK: отредактировано, чтобы сделать совместимым с обновленным вопросом