给定另一个

时间:2018-04-11 16:30:29

标签: r variables dataset recode

我正在使用一个数据集,其中对给定国家/地区的答案编码方式存在错误。让我们调用我的第一个变量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

3 个答案:

答案 0 :(得分:0)

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

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]]] )
})

答案 1 :(得分:0)

好的,谢谢大家,我根据你的答案自己找到解决方案。我用较少的变量创建了my.data的子集,这次内部函数工作没有错误。只有它的r2evans&#39;效果最佳的脚本,如下所示

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" })

欢呼并感谢您的时间和帮助!

答案 2 :(得分:0)

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][]

结果与上面显示的相同

可重复数据

为了测试上述解决方案,我从my.data的给定输出中重建了table(...)。请注意,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