【问题标题】:R: Recoding multiple dummy variables into a single variable and replacing the corresponding dummy value with the variable nameR:将多个虚拟变量重新编码为一个变量,并将对应的虚拟值替换为变量名
【发布时间】:2015-08-02 12:02:27
【问题描述】:

我有一个数据集,其中包含 14 个相互排斥的调用类型类别,全部编码为虚拟变量。这是一个小样本:

dput(df)
structure(list(MON1_12 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L), WEEK1_53 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), AGENT_ID = structure(c(3L, 
4L, 7L, 8L, 1L, 6L, 5L, 9L, 2L, 10L), .Label = c("A129", "A360", 
"A407", "B891", "D197", "L145", "L722", "O518", "T443", "W764"
), class = "factor"), CallsHandled = c(1L, 4L, 2L, 14L, 1L, 2L, 
5L, 1L, 1L, 3L), CONTENT = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L), CLAIMS = c(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), 
CREDIT_CARD = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), 
DEDUCT_BILL = c(0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L), 
HCREFORM = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("MON1_12", 
"WEEK1_53", "AGENT_ID", "CallsHandled", "CONTENT", "CLAIMS", 
"CREDIT_CARD", "DEDUCT_BILL", "HCREFORM"), class = "data.frame", row.names = c(NA, 
-10L))

我想将每个虚拟变量组合成一个名为“QUEUE”的新变量,该变量将“1”的值替换为相应虚拟变量的名称。这是一个示例:

dput(df2)
structure(list(MON1_12 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L), WEEK1_53 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), AGENT_ID = structure(c(3L, 
4L, 7L, 8L, 1L, 6L, 5L, 9L, 2L, 10L), .Label = c("A129", "A360", 
"A407", "B891", "D197", "L145", "L722", "O518", "T443", "W764"
), class = "factor"), CallsHandled = c(1L, 4L, 2L, 14L, 1L, 2L, 
5L, 1L, 1L, 3L), QUEUE = structure(c(1L, 4L, 2L, 4L, 1L, 3L, 
3L, 5L, 5L, 4L), .Label = c("CLAIMS", "CONTENT", "CREDIT_CARD", 
"DEDUCT_BILL", "HCREFORM"), class = "factor")), .Names = c("MON1_12", 
"WEEK1_53", "AGENT_ID", "CallsHandled", "QUEUE"), class = "data.frame", row.names = c(NA, 
-10L))

针对已标记的问题进行编辑:这是我今天下午根据建议尝试的方法,示例数据框略有不同:

df$Queue <- as.factor(df$CONTENT + df$CLAIMS*2 + df$CREDIT_CARD*3 +  df$DEDUCT_BILL*4 + df$HCREFORM*5)
levels(df$Queue) <- c("CONTENT", "CLAIMS", "CREDIT_CARD","DEDUCT_BILL","HCREFORM")
View(df)

但我在 Queue 列中收到一列 NA。所以,我在这里重新创建了另一个示例数据集。这个数据框充分代表了我在现实中将收到的内容,除了我将有大约 40 个变量和 200 万行。当我在上面的“df”上运行我上面尝试的内容时,我得到以下不正确的结果:

dput(df)
structure(list(MON1_12 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L), WEEK1_53 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), AGENT_ID = structure(c(3L, 
4L, 7L, 8L, 1L, 6L, 5L, 9L, 2L, 10L), .Label = c("A129", "A360", 
"A407", "B891", "D197", "L145", "L722", "O518", "T443", "W764"
), class = "factor"), CallsHandled = c(1L, 4L, 2L, 14L, 1L, 2L, 
5L, 1L, 1L, 3L), CONTENT = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L), CLAIMS = c(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), 
CREDIT_CARD = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), 
DEDUCT_BILL = c(0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L), 
HCREFORM = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), Queue = structure(c(2L, 
1L, 1L, 3L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("CONTENT", 
"CLAIMS", "CREDIT_CARD", "DEDUCT_BILL", "HCREFORM"), class = "factor")), .Names = c("MON1_12", 
"WEEK1_53", "AGENT_ID", "CallsHandled", "CONTENT", "CLAIMS", 
"CREDIT_CARD", "DEDUCT_BILL", "HCREFORM", "Queue"), row.names = c(NA, 
-10L), class = "data.frame")

我也试过了:

df3 <- cbind(df[1:4], QUEUE = apply(df[5:9], 1, function(N) names(N)[as.logical(N)]))

但收到以下错误:“data.frame 中的错误(“CLAIMS”,字符(0),字符(0),“DEDUCT_BILL”,: 参数暗示不同的行数:1、0:

【问题讨论】:

  • 到目前为止你尝试了什么?请分享任何尝试(编辑您的问题)。

标签: r


【解决方案1】:

您可以使用max.col 获取第 5 到第 9 列的每一行中值为“1”的列索引。(“df”示例不正确,因为大多数行都是 0。更正的一个如下)。

df$QUEUE <-  names(df)[-c(1:4)][max.col(df[-c(1:4)])]

或者你可以这样做

df$QUEUE <-  names(df)[-(1:4)][(as.matrix(df[-(1:4)]) %*% 
                         seq_along(df[-(1:4)]))[,1]]

更新

基于编辑数据集“df”,5:9 列的某些行全为“0”,在预期结果中,“QUEUE”显示为“CONTENT”。在这种情况下,我们可以先修改 'CONTENT' 列以更改行全为 0 的值,然后应用上述任一代码

 df$CONTENT[!rowSums(df[5:9])] <- 1
 df$QUEUE1 <-  names(df)[5:9][max.col(df[5:9])]
 df$QUEUE1
 #[1] "CLAIMS"      "CONTENT"     "CONTENT"     "DEDUCT_BILL" "CONTENT"    
 #[6] "CONTENT"     "CONTENT"     "CONTENT"     "CONTENT"     "CONTENT" 

数据

df <- structure(list(MON1_12 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L), WEEK1_53 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), 
AGENT_ID = structure(c(3L, 
4L, 7L, 8L, 1L, 6L, 5L, 9L, 2L, 10L), .Label = c("A129", "A360", 
"A407", "B891", "D197", "L145", "L722", "O518", "T443", "W764"
), class = "factor"), CallsHandled = c(1L, 4L, 2L, 14L, 1L, 2L, 
5L, 1L, 1L, 3L), CONTENT = c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0), CLAIMS = c(1, 
0, 0, 0, 1, 0, 0, 0, 0, 0), CREDIT_CARD = c(0, 0, 0, 0, 0, 1, 
1, 0, 0, 0), DEDUCT_BILL = c(0, 1, 0, 1, 0, 0, 0, 0, 0, 1),
 HCREFORM = c(0, 
0, 0, 0, 0, 0, 0, 1, 1, 0)), .Names = c("MON1_12", "WEEK1_53", 
"AGENT_ID", "CallsHandled", "CONTENT", "CLAIMS", "CREDIT_CARD", 
"DEDUCT_BILL", "HCREFORM"), row.names = c(NA, -10L), class = "data.frame")

【讨论】:

  • 非常感谢您解决我的另一个问题。出于某种原因,在运行您的第一个建议时,我获得了一个“QUEUE”列,其中该特定虚拟变量的名称中有任何“1”,例如,“QUEUE”列中的第 2 行显示“CONTENT”,但“ CONTENT”虚拟变量对于同一行是“0”,因此没有名称应该导致第 2 行列“QUEUE”。我得到的结果与你不同吗?
  • @user3594490 我的解决方案是基于这样一个假设,即您在单列的每一行中都有“1”。在您提供的第一个示例中,有些行只有 0。我不知道您如何使用这种数据选择列名。我错过了什么吗?
  • @user3594490 刚刚查看了您的编辑数据集。在这里,0 的行被命名为“CONTENT”。是这个条件吗?
  • @user3594490 我认为预期输出中的QUEUE 值对于第四个元素不正确。应该是DEDUCT_BILL。更新了帖子
  • 是的,您的编辑工作!我想我一直因为预期输出中的错误而让其他人失望。非常感谢!
【解决方案2】:

这应该会产生预期的结果:

df2 <- cbind(df[1:4], QUEUE = apply(df[5:9], 1, function(N) names(N)[as.logical(N)]))

假设在任何行中只有一个且恰好一个虚拟变量为 1(在您的 df 原始样本中并非如此)。

说明: df[1:4] 选择要保留在输出中的第一到第四列。然后使用cbind 函数将其绑定到QUEUE 的列。 QUEUE 是通过在数据集df 上逐行迭代虚拟变量(第 5 到第 9 列)并选择包含值 1 的列名来获得的。

【讨论】:

  • 我确实发布了一个旧版本的 df,但是当我在 R 中打开它时,我仍然没有在 5 个虚拟队列中看到重复的 1。实际上,它们对于每一行应该总是相互排斥的。有一些没有任何 1,这是我想在我打算上传的示例中更改的内容。但是这个数据框很可能是我在现实中得到的,有些队列没有调用某些代理。我尝试了您提供的此代码,但收到了我在上面编辑的错误。
  • 感谢这也适用于我的示例,但由于某种原因,我的大型数据集出现错误。 data.frame(..., check.names = FALSE) 中的错误:参数暗示不同的行数:267757、16。我不确定为什么我得到的行数不同。
  • @user3594490,检查any(rowSums(df[5:9]) != 1) 不是FALSENA
  • 我终于发现,即使在导入数据时使用了以下命令:mydata
猜你喜欢
  • 2018-03-22
  • 1970-01-01
  • 1970-01-01
  • 2015-10-28
  • 2020-08-02
  • 2016-03-07
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
相关资源
最近更新 更多