【问题标题】:Recode the value of a variable given the value of another one给定另一个变量的值,重新编码一个变量的值
【发布时间】:2018-04-11 16:30:28
【问题描述】:

我正在使用一个数据集,其中给定国家/地区的答案编码方式存在错误。让我们调用我的第一个变量my.data$country_year 和第二个变量my.data$attitude。两者的表格给出以下输出:

table(my.data$country_year, my.data$attitude)

       (1) Very Suitable (2) Suitable (3) Somewhat Suitable (4) Not Suitable                      
Yemen.2006    101            142             1192                       0
Lebanon.2007   13           14                    60                  1063
Yemen.2007       49          113                   122                  248
Palestine.2008    131          653                   387                2093

有问题的表格有很多国家,我在这个例子中省略了。我想做的是让 R 在我的原始数据集中执行以下操作,同时保留所有其他国家的观察结果:

for my.data$country="Yemen.2006" & my.data$attitude="(3) 有点适合", "(4) 不适合。

for my.data$country="Yemen.2006" & my.data$attitude="(2) 适合", "(3) 有点适合"

换句话说,我想将 2006 年在也门进行的调查的态度变量的第二个和第三个值向右移动,而不创建新变量。我希望结果如下

 (1) Very Suitable (2) Suitable (3) Somewhat Suitable (4) Not Suitable                      
Yemen.2006    101            0                   142                 1192                       
Lebanon.2007   13            14                    60                  1063
Yemen.2007       49          113                   122                  248
Palestine.2008    131          653                   387                2093

【问题讨论】:

  • 如果您指定tbl <- table(.),只需执行tbl[1, 2:4] <- tbl[1, c(4, 2, 3)]
  • 您是否尝试过within(mydata, { attitude[country=="Yemen.2007" & attitude=="(3)"] <- "(4)" }),其他国家/地区也类似? (确保在 2 到 3 之前移动 3 到 4,否则你将失去所有 2。)
  • Rui,您好,您提出的建议有效,但仅适用于一张桌子。根据我的示例,我想根据因子变量 country=Yemen 2006 对因子变量的态度重新排序。你知道用数据集做你建议的方法吗?
  • 您好 r2evans,您的解决方案正确地解决了我的问题的逻辑,但输入时 R 不接受它。它吐出如下错误:[<-.data.frame(*tmp*, nl, value = list(attitude= c(NA, NA, : duplicate subscripts for columns)

标签: r variables dataset recode


【解决方案1】:

我将假设态度是一个因素。在这种情况下,我们可以这样做

levels(my.data$attitude) <- levels(my.data$attitude)[c(1, 4, 2, 3)]

如果它还不是一个因素,就让它成为一个因素(至少暂时):

my.data$attitude <- factor(my.data$attitude)
levels(my.data$attitude) <- levels(my.data$attitude)[c(1, 4, 2, 3)]
my.data$attitude <- as.character(my.data$attitude)

仅更新 Yemen.2006 同样,假设态度是一个因素:

new_value_index <- c(1, 4, 2, 3)
my.data <- within(my.data, {
  attitude[country == "Yemen.2006"] <- levels(attitude)[new_value_index[attitude[country == "Yemen.2006]]] )
})

【讨论】:

  • 您好 Melissa,感谢您的 cmets,但我不想切换整个态度变量的级别,仅适用于也门 2006 年的观察结果(根据我提供的示例)。您的建议似乎改变了所有国家/地区观察的态度水平,对吗?
  • 非常感谢 Melissa,但我收到的错误消息与我收到的 r2evans 建议类似。你们俩都建议使用“within”命令,但对于两个建议的修复,我最终都收到以下错误: [tmp, nl, value = list(attitude = c(NA, NA, : 列的重复下标让我也澄清一下,我的两个变量确实是因素。
  • 我们可能需要一个可重现的示例来找出这些错误。 within 是一个不错的命令,可以让您在数据框中工作 - 请注意,我可以写 country 而不是 my.data$country。它返回一个数据帧,其中包含任何新定义的变量作为数据帧的新元素 - 所以它们的长度最好和以前一样!。
【解决方案2】:

好的,谢谢大家,我根据您的回答来寻找解决方案。我用较少的变量创建了 my.data 的一个子集,这次 inside 函数可以正常工作。只有 r2evans 的脚本效果最好,如下

my.data2 <- within(my.data2, {attitude[country_year=="Yemen.2006" & 
attitude=="(3) Somewhat Suitable"] <- "(4) Not Suitable At All" })

my.data2 <- within(my.data2, {attitude[country_year=="Yemen.2006" & 
attitude=="(2) Suitable"] <- "(3) Somewhat Suitable" })

干杯并感谢您的时间和帮助!

【讨论】:

    【解决方案3】:

    OP已经提到了

    有问题的表格有很多国家,我在这个例子中省略了。

    如果表很大并且只有几行要更新,我建议使用data.table,它通过引用只更新受影响的行而不复制整个数据对象。

    有两种方法:一种是选择和替换,另一种是使用带有查找表的更新连接

    选择和替换

    这类似于OP's own answer,但使用data.table 语法:

    library(data.table)
    setDT(my.data)[country_year == "Yemen.2006" & attitude == "(3) Somewhat Suitable", 
            attitude := "(4) Not Suitable"]
    my.data[country_year == "Yemen.2006" & attitude == "(2) Suitable", 
            attitude := "(3) Somewhat Suitable"]
    

    注意my.data 被修改就地,所以没有必要将结果分配给另一个数据框。结果可以通过以下任一方式验证

    dcast(my.data, country_year ~ attitude)
    

    table(my.data$country_year, my.data$attitude)
    
                     (1) Very Suitable (2) Suitable (3) Somewhat Suitable (4) Not Suitable
      Yemen.2006                   101            0                   142             1192
      Lebanon.2007                  13           14                    60             1063
      Yemen.2007                    49          113                   122              248
      Palestine.2008               131          653                   387             2093
    

    更新加入

    这里,预先创建了一个lookup 表,然后在连接中使用它来仅更新my.data 的匹配行:

    library(data.table)
    lookup <- data.table(
      country_year = "Yemen.2006", 
      attitude.old = c("(2) Suitable", "(3) Somewhat Suitable"),
      attitude.new = c("(3) Somewhat Suitable", "(4) Not Suitable"))
    setDT(my.data)[lookup, on = .(country_year, attitude == attitude.old), 
      attitude := attitude.new][]
    

    结果和上图一样

    可重现的数据

    为了测试上述解决方案,我从table(...) 的给定输出重构了my.data。请注意,my.data 是长格式,需要melt() 样本表并根据计数复制行的次数:

    DT_wide <- fread(
      "country_year, (1) Very Suitable, (2) Suitable, (3) Somewhat Suitable, (4) Not Suitable
    Yemen.2006,    101,            142,             1192,                       0
      Lebanon.2007,   13,           14 ,                   60,                  1063
      Yemen.2007   ,    49,          113,                   122,                  248
      Palestine.2008,    131,          653,                   387,                2093")
    DT_wide[, country_year := forcats::fct_inorder(country_year)]
    my.data <- melt(DT_wide, id = "country_year", variable.name = "attitude")[
      rep(1:.N, value)][, value := NULL][]
    
    my.data
    
            country_year          attitude
       1:     Yemen.2006 (1) Very Suitable
       2:     Yemen.2006 (1) Very Suitable
       3:     Yemen.2006 (1) Very Suitable
       4:     Yemen.2006 (1) Very Suitable
       5:     Yemen.2006 (1) Very Suitable
      ---                                 
    6377: Palestine.2008  (4) Not Suitable
    6378: Palestine.2008  (4) Not Suitable
    6379: Palestine.2008  (4) Not Suitable
    6380: Palestine.2008  (4) Not Suitable
    6381: Palestine.2008  (4) Not Suitable
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多