Странное поведение в replace () - PullRequest
0 голосов
/ 22 октября 2018

У меня есть набор данных об окружающей среде (env_PLI), где одна переменная - season_year.Два значения для этой переменной - «осень 2016» и «лето 2017».Для анализа мне нужно изменить переменную с символьной на числовую, поэтому я попытался изменить ее, чтобы уровни были только 2016 и 2017 гг.Тем не менее, код

env_PLI$season_year <- replace(env_PLI$season_year,
                       c("autumn 2016", "summer 2017"), c(2016, 2017))

дает мне ошибку

Error in `$<-.data.frame`(`*tmp*`, season_year, value = c("autumn 2016",  : 
  replacement has 52 rows, data has 50

Я попытался найти ее в Google, но результаты оказались менее чем полезными, так как они, как правило, говорили, что переменная должнабыть создан перед использованием replace (), но в моем случае я использую его для существующей переменной.Что еще я здесь не так делаю?

Ответы [ 4 ]

0 голосов
/ 22 октября 2018

Маркус объяснил, почему у вас проблема с replace, но решение, которое он дал, в некоторых случаях потерпит неудачу.

Существует несколько решений для изменения значений в векторе.

season_year <- c("A", "autumn 2016", "summer 2017", "summer 2017") 

plyr::mapvalues является прямой заменой вашего исходного кода.Я нахожу это наиболее полезным, когда у меня есть векторы from и to в data.frame, как словарь.

plyr::mapvalues(season_year, from = c("autumn 2016", "summer 2017"), to = c(2016, 2017))
[1] "A"    "2016" "2017" "2017"

dplyr::recode принимает пары старых и новых значений.

dplyr::recode(season_year, "autumn 2016" = "2016", "summer 2017" = "2017")
[1] "A"    "2016" "2017" "2017"

Вы можете использовать регулярные выражения для извлечения года.\\d{4} ищет последовательность из четырех цифр.Регулярные выражения очень эффективны, когда данные нуждаются в очистке.

gsub(pattern = ".*(\\d{4})", replacement = "\\1", season_year)
[1] "A"    "2016" "2017" "2017"
0 голосов
/ 22 октября 2018

Простите, если я неправильно истолковал ваш вопрос.

library(tidyverse)
dummydf<-data.frame(Id=c(1,2),Period=c("autumn 2006","spring 2007"))
#Change to character
dummydf %>% 
  mutate(Period=as.character(Period))
#Back to numeric
dummydf %>% 
  mutate(Period=as.numeric(Period))

Или, может быть, это

dummydf$Period %>% 
str_replace_all("autumn","")
0 голосов
/ 22 октября 2018

Вот несколько вариантов, которые вы можете рассмотреть:

readr::parse_number(c("autumn 2016", "summer 2017"))
# [1] 2016 2017
gsub("\\D","",c("autumn 2016", "summer 2017")) # could be wrapped into as.numeric
# [1] "2016" "2017"
0 голосов
/ 22 октября 2018

Учитывая вектор season_year <- c("A", "autumn 2016", "summer 2017") вызов

replace(season_year, c("autumn 2016", "summer 2017"), c(2016, 2017))

приводит к

#                                   autumn 2016   summer 2017 
# "A" "autumn 2016" "summer 2017"        "2016"        "2017" 

Когда вы смотрите на то, что replace делает

function (x, list, values) 
{
    x[list] <- values
    x
}

васможет обнаружить вашу ошибку: вы добавляете две записи к вашему вектору.Вот почему ошибка «замена имеет 52 строки, данные - 50» (в кадре данных должно быть одинаковое количество записей в каждом столбце).

Попробуйте %in% вместо

replace(season_year, season_year %in% c("autumn 2016", "summer 2017"), c(2016, 2017))
#[1] "A"    "2016" "2017"

note

Этот подход работает для фиктивного вектора выше.В случае, если не работает с вашими данными 1) попробуйте дать минимальный воспроизводимый пример и 2) просто попробуйте

env_PLI$season_year[env_PLI$season_year == "autumn 2016"] <- "2016"
env_PLI$season_year[env_PLI$season_year == "autumn 2017"] <- "2017"

или попробуйте

env_PLI$season_year <- gsub("(autumn|summer)\\s+", "", env_PLI$season_year)
# similar to @Moody_Mudskipper's second solution

Благодаря @RichardTelford и @Duckmayr.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...