Использование mutate над столбцами с кратными значениями для l oop для перекодирования значений - PullRequest
2 голосов
/ 05 января 2020

Мне нужно перекодировать значения для нескольких столбцов фрейма данных на основе другой таблицы.

Мне нужно перекодировать значения нескольких столбцов таблицы данных, используя боковую таблицу. Значения соответствуют географическим c идентификаторам, которые я должен заменить географическими названиями. Поэтому я решил сделать al oop, но то, что работает за пределами l oop, больше не работает. Я не могу использовать mutate для l oop.

Мои реальные данные содержат 274 столбца с 38 столбцами для перекодирования. Эти столбцы имеют много разных имен (они не являются местами вызова)

мой основной набор данных:

 id <- c(1, 2, 3)
 departure <- c(1, 2, NA)
 arrival <- c(3, 1, 2)
 transit <- c(NA,NA,1)
dataset <- data.frame(id, departure, arrival, transit)

Другая таблица:

geo_id <- c(1, 2, 3)
place_name <- c("Paris", "Nantes", "London")
geocode <- data.frame(geo_id, place_name)

Мой l oop:

var <- c("departure", "arrival", "transit") #the columns that should by recode (must be a vector with my  real data)

for (i in var) {
  print(i)
  dataset <- dataset %>% 
  mutate(i = geocode$place_name[match(i, geocode$geo_id)])

}

mutate создать новый вызов столбца i! Как избежать этого?

Ответы [ 4 ]

4 голосов
/ 05 января 2020

С dplyr вы можете сделать:

dataset %>%
 mutate_at(vars(one_of(var)), ~ geocode$place_name[match(., geocode$geo_id)])

  id place1 place2 place3
1  1  Paris London   <NA>
2  2 Nantes  Paris   <NA>
3  3   <NA> Nantes  Paris

Или с добавлением tidyr:

dataset %>%
 pivot_longer(one_of(var)) %>%
 left_join(geocode, by = c("value" = "geo_id")) %>%
 select(-value) %>%
 pivot_wider(names_from = name, values_from = place_name)
1 голос
/ 05 января 2020

Я думаю, вы хотите присоединиться к наборам данных. Вы можете использовать эту функцию dplyr и удалить ненужные столбцы.

comb <- dplyr::left_join(dataset, geocode, by = (c("id" = "geo_id")))
comb

  id place1 place2 place3 place_name
1  1      1      3     NA      Paris
2  2      2      1     NA     Nantes
3  3     NA      2      1     London
0 голосов
/ 05 января 2020

Возможно, есть более простые способы, но приведенный ниже код работает, и если вектор переменных для изменения var предварительно обрабатывается как один шаблон регулярного выражения, этот код кажется общим, не зависящим от количества или имен столбцов.

Часть этого вдохновлена ​​в этом ответе на другой вопрос. Вспомогательная функция f взята оттуда.

library(dplyr)
library(tidyr)

var_pattern <- paste(var, collapse = "|")

f <- function(.) if(length(unique(.[!is.na(.)])) > 1L) . else first(.[!is.na(.)]) 

dataset %>%
  gather(place, value, -id) %>%
  mutate(place_name = geocode$place_name[value]) %>%
  spread(place, place_name) %>%
  select(-value) %>%
  group_by(id) %>%
  mutate_at(vars(matches(var_pattern)), f) %>%
  ungroup() %>%
  distinct() %>% 
  filter(rowSums(is.na(.)) < 2L) 
## A tibble: 3 x 4
#     id place1 place2 place3
#  <dbl> <fct>  <fct>  <fct> 
#1     1 Paris  London NA    
#2     2 Nantes Paris  NA    
#3     3 NA     Nantes Paris 
0 голосов
/ 05 января 2020

Вот один из способов сделать:

# select cols to recode
cols <- c('place1','place2')

# get other columns
other_cols <- setdiff(colnames(dataset), cols)

# recode df
recode_df = sapply(cols, function(x) place_name[dataset[[x]]])

# get all columns together
df = cbind(recode_df, dataset[other_cols])
...