2016-06-21 7 views
0

Ниже представлены два простых кадра данных. Я хотел бы перекодировать (свернуть) столбцы Sat1 и Sat2 так, чтобы все степени удовлетворенности были закодированы просто как Satisfied, а все степени неудовлетворенности закодированы как Dissatisfied. Нейтральный будет оставаться нейтральным. Следовательно, эти факторы будут иметь три уровня - Satisfied, Dissatisfied, and Neutral.Перекодирование аналогичных уровней уровня в нескольких кадрах данных с использованием Purrr и Dplyr

я обычно сделать это путем привязки кадров данных, и с помощью lapply вместе с перекодировкой из car пакета, такие как:

DF1[2:3] <- lapply(DF1[2:3], recode, c('"Somewhat Satisfied"= "Satisfied","Satisfied"="Satisfied","Extremely Dissatisfied"="Dissatisfied"........etc, etc 

Я хотел бы сделать это, используя функцию карты, в частности, at_map (для сохранения фрейма данных, но я новичок в purrr, поэтому не стесняйтесь предлагать другие варианты карты) от purrr, а также dplyr, tidyr , stringr and ggplot2`, поэтому все может быть легко конвейерным.

Пример ниже - это то, что я хотел бы выполнить, но для повторного кодирования, но я не смог заставить его работать.

http://www.r-bloggers.com/using-purrr-with-dplyr/

Я хотел бы использовать at_map или аналогичную функцию карты, так что я могу сохранить исходные столбцы Sat1 и Sat2, поэтому повторно кодированные столбцы будут добавлены в кадр данных и переименован. Было бы здорово, если бы этот шаг также можно было включить в функцию.

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

Names<-c("James","Chris","Jessica","Tomoki","Anna","Gerald") 
Sat1<-c("Satisfied","Very Satisfied","Dissatisfied","Somewhat Satisfied","Dissatisfied","Neutral") 
Sat2<-c("Very Dissatisfied","Somewhat Satisfied","Neutral","Neutral","Satisfied","Satisfied") 
Program<-c("A","B","A","C","B","D") 
Pets<-c("Snake","Dog","Dog","Dog","Cat","None") 

DF1<-data.frame(Names,Sat1,Sat2,Program,Pets) 

Names<-c("Tim","John","Amy","Alberto","Desrahi","Francesca") 
Sat1<-c("Extremely Satisfied","Satisfied","Satisfed","Somewhat Dissatisfied","Dissatisfied","Satisfied") 
Sat2<-c("Dissatisfied","Somewhat Dissatisfied","Neutral","Extremely Dissatisfied","Somewhat Satisfied","Somewhat Dissatisfied") 
Program<-c("A","B","A","C","B","D") 


DF2<-data.frame(Names,Sat1,Sat2,Program) 
+0

Вы хотите, чтобы все ваши кадры данных были объединены в конце или сохранены в списке отдельно или ...? Это выглядит довольно просто с чем-то вроде 'mutate_each' от dplyr_0.4.3.9000 в сочетании с' map' или 'map_df'. 'map_at' похоже, что он заменяет текущие переменные, поэтому не может быть инструментом для использования в этом случае. – aosmith

+0

Спасибо за ваш ответ. Я полагаю, что это нормально, если кадры данных остаются в списке отдельно. Моя главная цель - найти быстрый способ (в конвейере purrr dplyr), который позволит мне перекодировать факторы в нескольких кадрах данных за один раз. Мне нравится идея объединения mutate_each и функции карты. Это нормально, если текущие переменные заменяются, поскольку я могу просто сделать копии кадров данных в первую очередь. Поэтому я был бы признателен, если бы вы могли показать код для своего примера. – Mike

ответ

1

Один из способов сделать это состоит в использовании mutate_each, чтобы сделать работу в сочетании с одним из map функций, чтобы идти по списку data.frames. Использование mutate_each или эквивалент от dplyr_0.4.3.9001 позволяет вам переименовывать новые столбцы.

В этом случае вместо перекодирования можно использовать строковые манипуляции. Я считаю, что вы хотите вытащить Satisfied, Dissatisfied, или Neutral из текущих строк, которые у вас есть. Вы можете достичь этого с помощью sub, используя регулярные выражения. Например,

sub(".*(Satisfied|Dissatisfied|Neutral).*$", "\\1", DF2$Sat2) 
"Dissatisfied" "Dissatisfied" "Neutral"  "Dissatisfied" "Satisfied" "Dissatisfied" 

Пакет stringr имеет хорошую функцию для извлечения определенных строк, str_extract.

library(stringr) 
str_extract(DF2$Sat2, "Satisfied|Neutral|Dissatisfied") 
"Dissatisfied" "Dissatisfied" "Neutral"  "Dissatisfied" "Satisfied" "Dissatisfied" 

Вы можете использовать это в mutate_each использовать одну из этих функций на нескольких столбцах. Имя, которое вы даете для функции в пределах funs, будет добавлено к новым именам столбцов. Я использовал recode.Для одного из ваших наборов данных:

DF1 %>% 
    mutate_each(funs(recode = str_extract(., "Satisfied|Neutral|Dissatisfied")), 
       starts_with("Sat")) 

    Names    Sat1    Sat2 Program Pets Sat1_recode Sat2_recode 
1 James   Satisfied Very Dissatisfied  A Snake Satisfied Dissatisfied 
2 Chris  Very Satisfied Somewhat Satisfied  B Dog Satisfied Satisfied 
3 Jessica  Dissatisfied   Neutral  A Dog Dissatisfied  Neutral 
4 Tomoki Somewhat Satisfied   Neutral  C Dog Satisfied  Neutral 
5 Anna  Dissatisfied   Satisfied  B Cat Dissatisfied Satisfied 
6 Gerald   Neutral   Satisfied  D None  Neutral Satisfied 

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

list(DF1, DF2) %>% 
    map(~mutate_each(.x, 
        funs(recode = str_extract(., "Satisfied|Neutral|Dissatisfied")), 
        starts_with("Sat"))) 

[[1]] 
    Names    Sat1    Sat2 Program Pets Sat1_recode Sat2_recode 
1 James   Satisfied Very Dissatisfied  A Snake Satisfied Dissatisfied 
2 Chris  Very Satisfied Somewhat Satisfied  B Dog Satisfied Satisfied 
... 
[[2]] 
     Names     Sat1     Sat2 Program Sat1_recode Sat2_recode 
1  Tim Extremely Satisfied   Dissatisfied  A Satisfied Dissatisfied 
2  John    Satisfied Somewhat Dissatisfied  B Satisfied Dissatisfied 
... 

Использование map_df вместо этого будет связывать все элементы в списке в data.frame, которые могут или не могут быть то, что вы хотите. Использование аргумента .id добавляет имя для каждого исходного набора данных.

list(DF1, DF2) %>% 
    map_df(~mutate_each(.x, 
        funs(recode = str_extract(., "Satisfied|Neutral|Dissatisfied")), 
        starts_with("Sat")), .id = "Group") 

    Group  Names     Sat1     Sat2 Program Pets Sat1_recode 
1  1  James    Satisfied  Very Dissatisfied  A Snake Satisfied 
2  1  Chris  Very Satisfied  Somewhat Satisfied  B Dog Satisfied 
3  1 Jessica   Dissatisfied    Neutral  A Dog Dissatisfied 
4  1 Tomoki Somewhat Satisfied    Neutral  C Dog Satisfied 
5  1  Anna   Dissatisfied    Satisfied  B Cat Dissatisfied 
6  1 Gerald    Neutral    Satisfied  D None  Neutral 
7  2  Tim Extremely Satisfied   Dissatisfied  A <NA> Satisfied 
8  2  John    Satisfied Somewhat Dissatisfied  B <NA> Satisfied 
... 
+0

Спасибо, это именно то, что я искал! – Mike

+0

список (DF1, DF2)%>% map (~ mutate (., SatREC = Sat1%>% recode ('"Чрезвычайно удовлетворен" = "Доволен"'))) – Mike

+0

Быстрый вопрос, используя ваш ответ выше, я также играл вокруг с использованием функции перекодирования автомобиля с картой и мутацией, которая работает. Код находится в комментарии выше. Но как бы я написал один и тот же код с mutate_each и включил как Sat1, так и Sat2? – Mike

1

я делать большие recodings, как это с объединением, в данном случае, я думаю, преобразующий к длинному dataframe делает проблему легче думать.

library(tidyr) 
library(dplyr) 

mdf <- DF1 %>% 
    gather(var, value, starts_with("Sat")) 

recode_df <- data_frame(value = c("Extremely Satisfied","Satisfied","Somewhat Dissatisfied","Dissatisfied"), 
         recode = 1:4) 
mdf <- left_join(mdf, recode_df) 
mdf %>% spread(var, recode) 
+0

Спасибо за ваш ответ. Это дало мне некоторые идеи, так как я не думал об использовании этого метода для перекодировки раньше. Однако я все еще надеюсь на ответ, который использует функцию отображения purrr. – Mike

+0

Ах, шаблон, вероятно, должен написать функцию 'f', которая перекодирует один вектор, затем используйте' df [] <- map_at (df, c ("SAT1", "SAT2"), f) ' – Shorpy

+0

Да, вот что я хочу делать. Думаю, теперь мне нужно выяснить эту функцию. У меня не было большого успеха, создавая функцию, чтобы свернуть факторы, как в моем примере выше. Можете ли вы помочь мне с кодом? – Mike