R: Преобразовать столбец dataframe, используя словарь / список? - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть столбец данных с многочисленными текстовыми значениями (уровнями).Мне нужно отобразить эти значения в предопределенную объектоподобную структуру, чтобы уменьшить количество уровней.Я мог бы легко добиться этого в Python, используя словарь, но не мог сделать то же самое со списком в R.

Например, мой столбец данных выглядит так:

df <- data.frame(weather = c('Clear','Snow','Clear','Rain','Rain','Other','Hail/sleet','Unknown'))

Мне нужносопоставьте это списку, подобному

weather.levels <- list(
  dry = c('Clear', 'Cloudy'),
  wet = c('Snow', 'Rain', 'Hail/sleet'),
  other = c('Other','Unknown'))

, чтобы мой преобразованный кадр данных выглядел как

    old.weather new.weather
1       Clear         dry
2        Snow         wet
3       Clear         dry
4        Rain         wet
5        Rain         wet
6      Other1       other
7  Hail/sleet         wet
8     Unknown       other

Я смотрел на такие решения, как this и this , но они не отвечают на мой вопрос.Я не могу создать фрейм данных для использования функции R match, потому что количество уровней в каждой категории предустановленного словаря weather.levels («сухой», «мокрый», «другой») различно.

Ответы [ 4 ]

0 голосов
/ 05 декабря 2018

Код:

sapply(df$weather, function(w) names(weather.levels[sapply(lapply(weather.levels, function(y) lapply(y, function(x) w %in% x)), function(z) any(z))]))

Затем свяжите его с df и измените имена столбцов.

0 голосов
/ 05 декабря 2018

Как это часто бывает, есть базовая функция R, предназначенная именно для этого.levels<- - это то, что вы хотите:

df$new.weather <- `levels<-`(df$weather, weather.levels)
df
#     weather new.weather
#1      Clear         dry
#2       Snow         wet
#3      Clear         dry
#4       Rain         wet
#5       Rain         wet
#6      Other       other
#7 Hail/sleet         wet
#8    Unknown       other

В немного более длинной, но более простой для чтения форме это эквивалентно:

df$new.weather <- df$weather
levels(df$new.weather) <- weather.levels
0 голосов
/ 05 декабря 2018

Есть три простых метода.Вначале я собираюсь немного изменить данные (убрать «Другое»), чтобы выделить одну из сильных сторон одного из методов.

df <- data.frame(weather = c('Clear','Snow','Clear','Rain','Rain','Other','Hail/sleet','Unknown'))
weather.levels <- list(
  dry = c('Clear', 'Cloudy'),
  wet = c('Snow', 'Rain', 'Hail/sleet'),
  other = c('Unknown'))

Простой поиск

levels1 <- c(Unknown="other",Snow="wet",Rain="wet","Hail/sleet"="wet",Clear="dry",Cloudy="dry")
### levels1 <- setNames(rep(names(weather.levels), lengths(weather.levels)), unlist(weather.levels))
transform(df, newwx = levels1[as.character(weather)])
#      weather newwx
# 1      Clear   dry
# 2       Snow   wet
# 3      Clear   dry
# 4       Rain   wet
# 5       Rain   wet
# 6      Other  <NA>
# 7 Hail/sleet   wet
# 8    Unknown other

(я использую transform, который является base-R, но вы можете легко использовать dplyr и такие, если вам удобнее.)

Объединение таблиц

По сути, это то, что делает ответ Шри (хотя концепция не только dplyr и друзья).

df2 <- data.frame(wxfrom = names(levels1), wxto = levels1, stringsAsFactors=FALSE, row.names=NULL)
merge(df, df2, by.x="weather", by.y="wxfrom", all.x=TRUE)
#      weather  wxto
# 1      Clear   dry
# 2      Clear   dry
# 3 Hail/sleet   wet
# 4      Other  <NA>
# 5       Rain   wet
# 6       Rain   wet
# 7       Snow   wet
# 8    Unknown other

Похоже на:

dplyr::left_join(df, df2, by=c("weather"="wxfrom"))

Lookup По умолчанию

transform(df, newwx = levels1[ match(as.character(weather), names(levels1), nomatch=1L) ])
#      weather newwx
# 1      Clear   dry
# 2       Snow   wet
# 3      Clear   dry
# 4       Rain   wet
# 5       Rain   wet
# 6      Other other
# 7 Hail/sleet   wet
# 8    Unknown other

Этот последний обладает врожденной способностью назначать неизвестное любым несоответствиям.С остальными это так же просто, как сделать ifelse(is.na(newwx), "unk", newwx), так что это не добавляет много.

0 голосов
/ 05 декабря 2018

Вот один из способов использования dplyr -

weather.levels %>% 
  unlist() %>% 
  data_frame(new.weather = gsub("[0-9]", "", names(.)), old.weather = .) %>% 
  left_join(df, ., by = c("weather" = "old.weather"))

     weather new.weather
1      Clear         dry
2       Snow         wet
3      Clear         dry
4       Rain         wet
5       Rain         wet
6      Other       other
7 Hail/sleet         wet
8    Unknown       other
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...