【问题标题】:Most efficient way to write a mapping function given a large CSV of recoded data给定大量重新编码数据的 CSV,编写映射函数的最有效方法
【发布时间】:2020-06-03 14:40:35
【问题描述】:

想象一下,我有一个从某人给我的大型 csv 加载的数据框,其中包含我想应用于其他数据集的数据映射/重新编码。这是 csv 中可能包含的内容的一个可重复的小示例:

library(wakefield)
csv_mapping <- data.frame(
  from = as.character(name(30)),
  to = as.character(likert_7(30))  
)

以独立于 csv 数据源的方式从此数据帧创建映射函数的最快方法是什么?我通常会通过运行来做到这一点:

dput(csv_mapping$from)
dput(csv_mapping$to)

在我的控制台中,然后我会将向量复制并粘贴到一个函数中并使用 plyr::mapvalues(),如下所示:

mapping_fn <- function(x) {

  fromvec <- c("Kameira", "Sanavi", "Avangelene", "Maryonna", "Wyvonna", "Enam", 
               "Yain", "Tyonna", "Shekira", "Eleanna", "Azriela", "Saajida", 
               "Chantee", "Julieanne", "Genisha", "Delesha", "Macenzi", "Alyasia", 
               "Latonga", "Josuhe", "Arter", "Stone", "Ramaj", "Lilinoe", "Zacharie", 
               "Joshuamichael", "Desseray", "Colorado", "Jaidn", "Verline")

  tovec <- c("Agree", "Somewhat Disagree", "Agree", "Agree", "Neutral", 
          "Somewhat Disagree", "Neutral", "Strongly Agree", "Somewhat Disagree", 
          "Disagree", "Strongly Disagree", "Disagree", "Somewhat Agree", 
          "Strongly Disagree", "Strongly Disagree", "Somewhat Agree", "Strongly Agree", 
          "Somewhat Agree", "Disagree", "Disagree", "Strongly Agree", "Strongly Disagree", 
          "Disagree", "Somewhat Agree", "Strongly Disagree", "Strongly Disagree", 
          "Neutral", "Somewhat Agree", "Agree", "Disagree")

  plyr::mapvalues(x, from = fromvec, to = tovec, warn_missing = F)

}

鉴于 plyr 现在被认为已退役,是否有更聪明或更快捷的方法可以在不使用 mapvalues 的情况下做到这一点?

【问题讨论】:

    标签: r dplyr plyr


    【解决方案1】:

    使用来自dplyr 包的recode 的一个非常简单的解决方案

    level_key <- setNames(csv_mapping$to, csv_mapping$from)
    dplyr::recode(csv_mapping$from, !!!level_key)
    

    基本上我们创建 named 向量 level_key 包含键值对,然后我们在 recode 函数中使用取消引用拼接。


    例子

    library(wakefield)
    set.seed(42)
    csv_mapping <- data.frame(
      from = as.character(name(5)),
      to = as.character(likert_7(5))  
    )
    csv_mapping
    
    #       from                to
    # 1 Merrissa Strongly Disagree
    # 2  Lilbert           Neutral
    # 3  Rudelle    Strongly Agree
    # 4  Kaymani Somewhat Disagree
    # 5   Kenadi          Disagree
    
    level_key <- setNames(csv_mapping$to, csv_mapping$from)
    dplyr::recode(csv_mapping$from, !!!level_key)
    # [1] "Strongly Disagree" "Neutral"           "Strongly Agree"    "Somewhat Disagree" "Disagree"
    

    【讨论】:

    • 啊——这就是我需要的——我会在下面的另一个答案中写下函数方法!谢谢!
    【解决方案2】:

    一个自然的方法是使用join。如果您的数据已经在数据框中,这将特别有用,但如果您真的只想要映射值的向量,您可以对其进行处理。

    假设我们有一个由 csv 定义的映射,如下所示:

    csv_mapping <- data.frame(from = c("Kameira", "Sanavi", "Avangelene", 
                                       "Maryonna", "Wyvonna"),
                              to = c("Agree", "Somewhat Disagree", "Agree",
                                     "Agree", "Neutral"))
    
    csv_mapping
    #>         from                to
    #> 1    Kameira             Agree
    #> 2     Sanavi Somewhat Disagree
    #> 3 Avangelene             Agree
    #> 4   Maryonna             Agree
    #> 5    Wyvonna           Neutral
    

    然后假设我们有一个数据框df,其中x 列给出了我们想要映射到新值的值。请注意df 还可以包含其他列,在这种情况下,我们将添加一些随机值进行演示。

    df <- data.frame(x = c("Sanavi", "Maryonna", "Maryonna", "Wyvonna",
                           "Kameira","Avangelene", "Sanavi", "Wyvonna"),
                     vals = rnorm(8))
    
    df
    #>            x        vals
    #> 1     Sanavi -0.95005745
    #> 2   Maryonna -0.20650715
    #> 3   Maryonna -0.07755789
    #> 4    Wyvonna  1.72379970
    #> 5    Kameira -1.36642679
    #> 6 Avangelene -1.48638577
    #> 7     Sanavi  0.16987157
    #> 8    Wyvonna -0.55194346
    

    然后,我们可以使用 dplyr 的 left_join 将映射值引入数据帧。 (您可以阅读更多here)。

    dplyr::left_join(df, csv_mapping, by = c("x" = "from"))
    #>            x        vals                to
    #> 1     Sanavi -0.95005745 Somewhat Disagree
    #> 2   Maryonna -0.20650715             Agree
    #> 3   Maryonna -0.07755789             Agree
    #> 4    Wyvonna  1.72379970           Neutral
    #> 5    Kameira -1.36642679             Agree
    #> 6 Avangelene -1.48638577             Agree
    #> 7     Sanavi  0.16987157 Somewhat Disagree
    #> 8    Wyvonna -0.55194346           Neutral
    

    此时,您从给定映射中获得了每个x 值对应的to 值。如果您只想要那些 to 值,您可以简单地从数据框中拉出 to 列。

    reprex package (v0.3.0) 于 2020 年 6 月 3 日创建

    【讨论】:

      【解决方案3】:

      所以根据上面 Ric S 的回答,我可以使用我原来的方法,但使用 dplyr 而不是 plyr,如下所示:

      mapping_fn <- function(x) {
      
          fromvec <-  c("Kameira", "Sanavi", "Avangelene", "Maryonna", "Wyvonna", "Enam", 
                       "Yain", "Tyonna", "Shekira", "Eleanna", "Azriela", "Saajida", 
                       "Chantee", "Julieanne", "Genisha", "Delesha", "Macenzi", "Alyasia", 
                       "Latonga", "Josuhe", "Arter", "Stone", "Ramaj", "Lilinoe", "Zacharie", 
                       "Joshuamichael", "Desseray", "Colorado", "Jaidn", "Verline")
          
          tovec <- c("Agree", "Somewhat Disagree", "Agree", "Agree", "Neutral", 
                     "Somewhat Disagree", "Neutral", "Strongly Agree", "Somewhat Disagree", 
                     "Disagree", "Strongly Disagree", "Disagree", "Somewhat Agree", 
                     "Strongly Disagree", "Strongly Disagree", "Somewhat Agree", "Strongly Agree", 
                     "Somewhat Agree", "Disagree", "Disagree", "Strongly Agree", "Strongly Disagree", 
                     "Disagree", "Somewhat Agree", "Strongly Disagree", "Strongly Disagree", 
                     "Neutral", "Somewhat Agree", "Agree", "Disagree")
      
        
          level_key <- setNames(tovec, fromvec)
          dplyr::recode(x, !!!level_key)
          
      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-13
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多