【问题标题】:Working with data values (dictionary). dataframes and recoding in R使用数据值(字典)。 R中的数据帧和重新编码
【发布时间】:2021-07-21 19:53:13
【问题描述】:

我正在尝试使用包含 30 个左右变量的 data.frame。这些变量都有不同的数值(例如,“0”或“32”)。数值映射到字符串(例如,在变量 Q1 中,“0”是“Urban”;在变量 Q6 中,“32”是“不可用”)。

我在网上看到了 recode 的一些用途,还有一个旧的 plyr 包进行了这种映射,以及 match 函数,但我没有找到任何与我所拥有的确切结构相匹配的东西。

我在下面提供了一个可重现的示例:

  test <- as.data.frame(c("1", "2", "3"))
  colnames(test) <- "Q1"
    
  dictionary <- as.data.frame(c("1", "2", "3"))
  dictionary$values <- c("dog", "fish", "cat")
  dictionary$question <- c("Q1", "Q1", "Q1")
  colnames(dictionary)[1] <- "keys"

所以,在这里,dictionary$question 包含要映射到的问题;然后“键”和“值”提供映射。因此,在测试数据框中,我有一个变量 (Q1),它采用三个可能的值,“1”、“2”或“3”。我需要将它们映射回“狗”、“鱼”、“猫”。

但我需要一种自动方式将目标数据框中的列映射到字典中的行,然后转换值,因为实际上我有超过 1000 个可能的值和 30 个变量。

编辑:我期望的是这样的函数或命令:

fun(test, dictionary)

输出:带有c("dog", "fish", "cat") 的data.frame。

或者,如果测试是c("1", "1", "1"),那么它将是c("dog", "dog", "dog")

【问题讨论】:

    标签: r dictionary match


    【解决方案1】:

    如果有很多列,循环across'test'列,匹配并替换从'dictionary'的subset创建的命名向量中的值,其中'question'与相应的列名匹配( cur_column()) 然后使用coalesce 用原始数据值填充任何 NA 值

    library(dplyr)
    library(tibble)
    test %>%
          mutate(across(everything(), ~ 
         coalesce(deframe(subset(dictionary, question == cur_column(), 
              select= -question))[as.character(.)], as.character(.))))
        Q1
    1  dog
    2 fish
    3  cat
    

    或者为了防止多次调用as.character,执行一次

    test %>%
       mutate(across(everything(), as.character),
              across(everything(), 
               ~coalesce(deframe(subset(dictionary, question == cur_column(), 
              select= -question))[.], .)))
     Q1
    1  dog
    2 fish
    3  cat
    

    或使用base R

    lst1 <- split(dictionary[-3], dictionary$question)
    test[names(lst1)] <- Map(function(x, y) {
        tmp <- with(y,  setNames(values, keys)[as.character(x)])
         tmp[is.na(tmp)] <- x[is.na(tmp)]
         tmp}, test[names(lst1)], lst1)
    

    【讨论】:

    • 您好 Akrun,非常感谢您抽出宝贵时间。您的解决方案似乎很棒,并且适用于我的测试数据框。但是,当在我的常规数据框中使用它时,我想出了消息“错误:mutate() 输入 ..1.; x 无法组合 ..1 ..2 .;我输入..1across(...)。”知道可能是什么原因造成的吗?我可以分享一些例子来试试这个
    • @jpugliese 我改变了它。我之前就想过这个问题。谢谢。只是'test'中的原始列是数字/整数,所以当你合并时,它应该是一个相同的类型。,在更新的一个中,我用as.character
    • 这很完美!我可以测试我是否理解正在发生的事情吗?首先,我们使用cross(, as.character) 打开,它将所有列转换为字符。然后,我们再次应用,这次我们运行一个函数。从内到外,我们subset字典,寻找以我们当前列命名的行(例如,这里的Q1,存储在变量“question”中)。我们选择与其关联的列,而不是“问题”本身。然后我们有一个只包含这些行的 data.frame。然后我们对其进行解构。最后的 coalesce( ,.) 在做什么?还有[.]?再次感谢您!
    • @jpugliese 你是对的。关于最后一部分,它只是保留原始列值,以防您在字典数据集中没有任何键/值对。否则,它返回 NA。 coalesce 将第一个参数作为匹配的参数,确保为每个参数返回相应的第一个非 NA 元素,因此如果您有类似 coalesce(c(NA, 'a', 'b'), c('a', NA, 'b'))[1] "a" "a" "b" 的内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 2017-01-31
    • 2021-01-24
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多