【问题标题】:Recoding Similar Factor Levels Across Multiple Data Frames Using Purrr and Dplyr使用 Purrr 和 Dplyr 在多个数据帧中重新编码相似的因子水平
【发布时间】:2016-10-23 10:26:03
【问题描述】:

下面是两个简单的数据框。我想重新编码(折叠)Sat1Sat2 列,以便所有满意程度都简单地编码为Satisfied,所有不满意程度都编码为Dissatisfied。中性将保持中性。因此,这些因素将具有三个级别 - Satisfied, Dissatisfied, and Neutral

我通常会通过绑定数据帧并使用lapply 以及car 包中的重新编码来完成此操作,例如:

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

我想使用地图功能来完成这项工作,特别是来自purrrat_map(维护数据框,但我是purrr 的新手,所以请随时建议其他版本的地图),以及如dplyr, tidyr,stringrandggplot2` 所以一切都可以很容易地流水线化。

下面的例子是我想要完成的,但是为了重新编码,但我无法让它工作。

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

我想使用at_map或类似的map函数,这样我就可以保留Sat1Sat2的原始列,所以重新编码的列将被添加到数据框中并重命名。如果这个步骤也可以包含在一个函数中,那就太好了。

实际上,我会有很多数据框,所以我只想重新编码一次因子水平,然后使用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)

【问题讨论】:

  • 您希望所有数据帧最终合并还是单独存储在一个列表中,还是...?这似乎相当简单,例如来自 dplyr_0.4.3.9000 的 mutate_each 结合 mapmap_dfmap_at 看起来像是替换了当前变量,所以可能不是在这种情况下使用的工具。
  • 感谢您的回复。我想如果数据框单独保留在列表中就可以了。我的主要目标是找到一种快速方法(在 purrr dplyr 管道中),这将允许我一次性重新编码跨多个数据帧的因素。我喜欢结合 mutate_each 和 map 函数的想法。如果当前变量被替换就可以了,因为我可以先复制数据帧。因此,如果您能展示您的示例的代码,我将不胜感激。

标签: r dplyr purrr


【解决方案1】:

我使用连接进行这样的大型重新编码,在这种情况下,我认为转换为长数据帧会使问题更容易思考。

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)

【讨论】:

  • 感谢您的回复。它给了我一些想法,因为我以前没有考虑过使用这种方法重新编码。但是我仍然希望得到一个使用 purrr 映射函数的答案。
  • 啊,那里的模式大概是写一个函数f重新编码一个向量,然后使用df[] &lt;- map_at(df, c("SAT1", "SAT2"), f)
  • 是的,这就是我想做的。我想现在我需要弄清楚这个功能。我没有成功创建一个函数来折叠我上面例子中的因素。你能帮我写代码吗?
  • 现在没时间了,但是对于矢量v,请为每个重新编码步骤执行v[v == "Very Satisfied"] &lt;- "Satisfied" 之类的操作。这就是我认为联接更容易的部分原因。
【解决方案2】:

执行此操作的一种方法是使用mutate_eachmap 函数之一结合使用以遍历data.frames 列表。使用 mutate_eachdplyr_0.4.3.9001 中的等效项允许您重命名新列。

在这种情况下,您可以使用字符串操作而不是重新编码。我相信您想从您拥有的当前字符串中提取SatisfiedDissatisfiedNeutral。您可以使用正则表达式通过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

要遍历存储在列表中的许多数据集,您可以使用 purrr 中的 map 函数对列表中的每个元素执行函数。

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
...

【讨论】:

  • 谢谢,这正是我想要的!
  • list(DF1,DF2)%>%map(~mutate(.,SatREC=Sat1 %>% recode('"Extremely Satisfied"="Satisfied"')))
  • 快速问题,使用您上面的答案,我还尝试使用带有地图和变异的汽车重新编码功能,这很有效。代码在上面的评论中。但是,我如何使用 mutate_each 编写相同的代码,并同时包含 Sat1 和 Sat2?
  • 与答案中的代码一样,您可以使用starts_with 函数处理以“Sat”开头的所有变量。如果您将 recode 代码代替 str_extract 代码,它应该可以正常工作。请注意 mutate_each 中的 . 代表您正在变异的变量,因此您将不再像在 mutate 代码中那样对变量名称进行硬编码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
相关资源
最近更新 更多