У меня есть фрейм данных, в котором я хочу проверить какое-то условие, и мне нужно добавить новый столбец на основе результата условия.
Это мои входные данные
InputData = data.frame(A = c("", "", "Apple"), B = c("", "", "Orange"), C = c("", "", ""), D = c(0, 1, 1))
Это мой желаемый результат
OutputData = InputData %>%
mutate(R = case_when(A=='' & B=='' & C=='' & D==0 ~ "Yes", TRUE ~ "No"))
Я пробовал мутировать с помощью функции Case. Он работает нормально, но это занимает больше времени, когда у меня больше строк.
Пожалуйста, помогите мне сделать это быстрее.
В моем фрейме данных более 1 lac строк, а столбец D является числовым столбцом. Эти входные данные - всего лишь пример моей постановки задачи.
Я удивлен, что ваш код работает медленно с такими небольшими данными (всего 100 тыс. строк). Я бы сделал это так:
InputData$R <- "No"
InputData[InputData$A == '' & InputData$B == '' &
InputData$C == '' & InputData$D == 0, "R"] <- "Yes"
Однако я настоятельно рекомендую использовать логические значения вместо «Да»/«Нет»:
InputData$S <- InputData$A == '' & InputData$B == '' &
InputData$C == '' & InputData$D == 0
# A B C D R S
#1 0 Yes TRUE
#2 1 No FALSE
#3 Apple Orange 1 No FALSE
Если это все еще слишком медленно, пакет data.table может помочь. Но в этом нет необходимости, если только данные не станут действительно большими.
Я использовал это решение с логическими значениями. Сейчас это быстро. Большое спасибо за решение @Roland
Далее следует простой тест. Кажется, что если вы просто хотите разделить столбец на две части, if_else
предпочтительнее case_when
в dplyr
. Если вас волнует скорость, измените рабочий процесс на base
, как @Roland answer.
InputData = data.frame(A = sample(c('x', ''), 1e5, TRUE),
B = sample(c('x', ''), 1e5, TRUE),
C = sample(c('x', ''), 1e5, TRUE),
D = sample(0:1, 1e5, TRUE))
library(dplyr)
bench::mark(
"base::ifelse" = InputData %>% mutate(R = ifelse(A == '' & B == '' & C == '' & D == 0, "Yes", "No")),
"dplyr::case_when" = InputData %>% mutate(R = case_when(A == '' & B == '' & C == '' & D == 0 ~ "Yes", TRUE ~ "No")),
"dplyr::if_else" = InputData %>% mutate(R = if_else(A == '' & B == '' & C == '' & D == 0, "Yes", "No")),
"base::repalce" = InputData %>% mutate(R = "No", R = replace(R, A == '' & B == '' & C == '' & D == 0, "Yes")),
"base::`[<-`.Roland" = local({
InputData$R <- "No"
InputData$R[InputData$A == '' & InputData$B == '' & InputData$C == '' & InputData$D == 0] <- "Yes"
InputData
}),
iterations = 100
)
# # A tibble: 5 × 9
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm>
# 1 base::ifelse 24.87ms 25.82ms 38.0 7.63MB 17.1 69 31 1.82s
# 2 dplyr::case_when 15.65ms 16.91ms 57.0 8.4MB 24.4 70 30 1.23s
# 3 dplyr::if_else 6.77ms 7.17ms 133. 6.87MB 39.6 77 23 580.57ms
# 4 base::repalce 5.6ms 5.9ms 166. 5.75MB 36.4 82 18 495.1ms
# 5 base::`[<-`.Roland 3.47ms 3.52ms 269. 3.84MB 33.2 89 11 331.35ms
Почему вы копируете весь data.frame, когда хотите просто добавить столбец? Насколько велик ваш data.frame? Каковы типы данных/классы столбцов от A до D? Является ли
D
действительно столбцом символов, как в примере? Почему это не числовое значение сNA
для пропущенных значений?