Как заменить уровни факторов в кратных столбцах фрейма данных на основе фрейма данных поиска соответствия, используя R - PullRequest
0 голосов
/ 14 декабря 2018

Уровни в df1, которые соответствуют lab_pt в dataframe lookup_df, я хотел бы заменить соответствующими уровнями во втором столбце lookup_df (это здесь: lab_en).Но я хочу оставить все как есть.Большое спасибо!

--

Основной кадр данных

df1 <- data.frame(
            num_var = sample(200, 15),
            col1 = rep(c("onda","estrela","rato","caneta","ceu"), 3),
            col2 = rep(c("muro","gato","pa","rato","ceu"), 3),
            col3 = rep(c("surf","onda","dente","onda","sei"), 3),
            col3 = rep(c("onda","casa",NA,"nao","net"), 3))

Кадр данных Lookeup

lookup_df <- data.frame(
            lab_pt = c("onda","estrela","rato","caneta","ceu"),
            lab_en = c("wave","star","rat","pen","sky"))

Я попробовал это здесь ниже.Он выполняет свою работу, но несоответствующая информация преобразуется в NA, а я этого не хочу.

rownames(lookup_df) <- lookup_df$lab_pt
apply(df1[,2:ncol(df1)], 2, function(x) lookup_df[as.character(x),]$lab_en)

Этот пост здесь довольно похож, но в этом случае все уровни сопоставимы, отличаются отэто здесьБольшое спасибо! Заменить значения в кадре данных на основе справочной таблицы

Ответы [ 4 ]

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

Вот решение с использованием пакета dplyr.Обратите внимание на аргумент stringAsFactor=F для сохранения слов в виде строк.

   df1 <- data.frame(
      num_var = sample(200, 15),
      col1 = rep(c("onda","estrela","rato","caneta","ceu"), 3),
      col2 = rep(c("muro","gato","pa","rato","ceu"), 3),
      col3 = rep(c("surf","onda","dente","onda","sei"), 3),
      col3 = rep(c("onda","casa",NA,"nao","net"), 3), stringsAsFactors = F)

    lookup_df <- data.frame(
      lab_pt = c("onda","estrela","rato","caneta","ceu"),
      lab_en = c("wave","star","rat","pen","sky"), stringsAsFactors = F)


    library(dplyr)

    df1 %>% mutate(col1=replace(col1, col1 %in% lookup_df$lab_pt, lookup_df$lab_en)) %>% 
      mutate(col2=replace(col2, col2 %in% lookup_df$lab_pt, lookup_df$lab_en)) %>% 
      mutate(col3=replace(col3, col3 %in% lookup_df$lab_pt, lookup_df$lab_en)) %>%
      mutate(col3.1=replace(col3.1, col3.1 %in% lookup_df$lab_pt, lookup_df$lab_en))

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

   num_var col1 col2  col3 col3.1
1        6 wave muro  surf   wave
2       84 star gato  wave   casa
3      146  rat   pa dente   <NA>
4      133  pen wave  star    nao
5       47  sky star   sei    net
6      116 wave muro  surf   star
7       81 star gato   rat   casa
8      118  rat   pa dente   <NA>
9      186  pen  rat   pen    nao
10     161  sky  pen   sei    net
11     135 wave muro  surf    rat
12      31 star gato   sky   casa
13     174  rat   pa dente   <NA>
14     187  pen  sky  wave    nao
15     178  sky wave   sei    net
0 голосов
/ 14 декабря 2018

Я думаю, что это может помочь вам, хотя и создаст новый столбец, но сделает всю работу

df1$new <- lookup_df[match(df1$col1, lookup_df$lab_pt),2]
0 голосов
/ 14 декабря 2018

Вы можете сделать что-то вроде следующего:

lookup_vec <- setNames(as.character(lookup_df[["lab_en"]]), lookup_df[["lab_pt"]])
#   onda estrela    rato  caneta     ceu 
# "wave"  "star"   "rat"   "pen"   "sky" 
factors_vars <- names(df1)[sapply(df1, is.factor)]
for (var in factors_vars) {
  w <- which(levels(df1[[var]]) %in% names(lookup_vec)) # Get only those that are "matchable"
  levels(df1[[var]])[w] <- lookup_vec[levels(df1[[var]])[w]]
}
df1

   num_var col1 col2  col3 col3.1
1       21 wave muro  surf   wave
2      104 star gato  wave   casa
3       60  rat   pa dente   <NA>
4      183  pen  rat  wave    nao
5      123  sky  sky   sei    net
6       17 wave muro  surf   wave
7       34 star gato  wave   casa
8      126  rat   pa dente   <NA>
9      139  pen  rat  wave    nao
10      35  sky  sky   sei    net
11     149 wave muro  surf   wave
12       8 star gato  wave   casa
13      46  rat   pa dente   <NA>
14      32  pen  rat  wave    nao
15     162  sky  sky   sei    net
0 голосов
/ 14 декабря 2018

Я думаю, что это следует сделать с пакетом data.table.Это переупорядочить идентификаторы, это проблема?

# added seed
# changed col3 to col4
set.seed(1)
df1 <- data.frame(
  num_var = sample(200, 15),
  col1 = rep(c("onda","estrela","rato","caneta","ceu"), 3),
  col2 = rep(c("muro","gato","pa","rato","ceu"), 3),
  col3 = rep(c("surf","onda","dente","onda","sei"), 3),
  col4 = rep(c("onda","casa",NA,"nao","net"), 3))

lookup_df <- data.frame(
  lab_pt = c("onda","estrela","rato","caneta","ceu"),
  lab_en = c("wave","star","rat","pen","sky"))

# data.table solution
library(data.table)

# change from wide to long, to make merge easier
dt <- melt(as.data.table(df1), id.vars="num_var")

# merge in the new values to original data
dt2 <- merge(dt, lookup_df, by.x="value", by.y="lab_pt",
             all.x=TRUE)

# if its missing, replace with original value
dt2[is.na(lab_en), lab_en := value]

# convert back from long to wide
dt3 <- dcast(dt2[, .(num_var, variable, lab_en)], num_var~variable,
            value.var="lab_en")

# back to data.frame
output <- as.data.frame(dt3)

Всякий раз, когда вы выполняете слияние между таблицами, обычно лучше работать с данными длинного формата, где у вас есть столбец группы и столбец значений.Это означает, что вам не нужно запускать одну и ту же операцию несколько раз (объединение).

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