#r #dataframe
#r #фрейм данных
Вопрос:
У меня есть фрейм данных DF
:
DF <- data.frame(V1 = factor(c("Yes", "No", "Yes", "No", "No")),
V2 = factor(c("Yes", "No", "No", "Yes", "No")),
Location = factor(c("London", "Paris", "No", "Dallas", "No")),
V3 = factor(c("No", "Yes", "No", "No", "No")),
V4 = factor(c("No", "Yes", "No", "No", "No")))
Я хочу изменить значения "No"
в переменных V1
, V2
, V3
и V4
— но не Location
— на "X"
. Я могу легко изменить названия уровней вручную в каждом отдельном столбце, но это отнимает много времени в большом наборе данных. Однако, если я использую revalue
, то каждый из них "No"
, включая те в Location
, которые я хочу оставить неизменными, изменяется на "X"
:
library("plyr")
as.data.frame(lapply(DF, function(x) { revalue(x, c("No"="X")) }))
Есть ли способ указать переменные на основе их положения в наборе данных (здесь столбцы 1: 2 и 4: 5), к которым применяется переименование?
Комментарии:
1. Просто примечание:
data.frame
общеизвестно, что строки по умолчанию преобразуются в факторы, поэтомуfactor()
часть вашего примера избыточна.
Ответ №1:
Еще одно решение, использующее лямбда-код в стиле запроса dplyrs ~ fun(.)
в качестве .funs
аргумента в сочетании с forcats::fct_recode:
library("dplyr")
library("forcats")
(DF <- DF %>%
mutate_at(vars(-Location), ~fct_recode(., "X" = "No")))
# V1 V2 Location V3 V4
# 1 Yes Yes London X X
# 2 X X Paris Yes Yes
# 3 Yes X No X X
# 4 X Yes Dallas X X
# 5 X X No X X
Обновление для dplyr 1.0:
Новое across()
заменяет семейство «вариантов с ограниченной областью действия», подобное mutate_at
. across()
упрощает применение одного и того же преобразования к нескольким столбцам, позволяя использовать семантику select() внутри в summarise() и mutate()
Применительно к вопросу здесь, ниже приведены 2 варианта для достижения этого:
DF %>%
mutate(across((!Location), ~fct_recode(., "X" = "No")))
DF %>%
mutate(across(c(1:2,4:5), ~fct_recode(., "X" = "No")))
Ответ №2:
Просто укажите номера столбцов, к которым вы хотите применить revalue
функцию:
cols_to_update <- c(1:2,4:5)
DF[, cols_to_update] <- lapply(DF[,cols_to_update], function(x) plyr::revalue(x, c("No"="X")))
Ответ №3:
Возможно, кто-то может предложить более элегантное решение, однако решение, которое работает (без изменения каждой переменной вручную), заключается в следующем:
change.vec = c("V1", "V2", "V3", "V4")
for(i in 1:length(change.vec)) {
levels(DF[,change.vec[i]]) = c("X", "Yes")
}
>DF
V1 V2 Location V3 V4
1 Yes Yes London X X
2 X X Paris Yes Yes
3 Yes X No X X
4 X Yes Dallas X X
5 X X No X X
Ответ №4:
Вы также можете сделать это, используя подход tidyverse:
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(plyr)
#> -------------------------------------------------------------------------
#> You have loaded plyr after dplyr - this is likely to cause problems.
#> If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
#> library(plyr); library(dplyr)
#> -------------------------------------------------------------------------
#>
#> Attaching package: 'plyr'
#> The following objects are masked from 'package:dplyr':
#>
#> arrange, count, desc, failwith, id, mutate, rename, summarise,
#> summarize
DF <- data.frame(V1 = factor(c("Yes", "No", "Yes", "No", "No")),
V2 = factor(c("Yes", "No", "No", "Yes", "No")),
Location = factor(c("London", "Paris", "No", "Dallas", "No")),
V3 = factor(c("No", "Yes", "No", "No", "No")),
V4 = factor(c("No", "Yes", "No", "No", "No")))
(DF <- DF %>%
mutate_at(.vars = vars(-Location),
.funs = function(t) revalue(x = t,
replace = c("No" = "X"))))
#> V1 V2 Location V3 V4
#> 1 Yes Yes London X X
#> 2 X X Paris Yes Yes
#> 3 Yes X No X X
#> 4 X Yes Dallas X X
#> 5 X X No X X
Создано 2019-03-17 пакетом reprex (версия 0.2.1)