我需要帮助将具有特定值的数据帧转换为看起来像R中的对比的列。 例如。
code <- data.frame(code = c('R1111', 'R1112', 'R1111', 'R1111', 'R1113',
'R1112', 'R1112', 'R1112', 'R1113', 'R1115'))
我需要将其转换为下表
code R1111 R1112 R1113 R1115
1 R1111 1 0 0 0
2 R1112 0 1 0 0
3 R1111 2 0 0 0
4 R1111 3 0 0 0
5 R1113 0 0 1 0
6 R1112 0 2 0 0
7 R1112 0 3 0 0
8 R1112 0 4 0 0
9 R1113 0 0 2 0
10 R1115 0 0 0 1
我有1400行,我需要转换那些类型的代码。如果您注意到,带有代码的每列都有不断增加的数字。我尝试使用reshape2
执行此操作,但我一直收到错误 - 这意味着我无法弄清楚这一点。我怎样才能得到这个结果?
答案 0 :(得分:2)
选项是将mapply
与ifelse
结合使用,以获得所需的结果:
cbind(code,mapply(function(x){
ifelse(code$code==x,cumsum(code$code==x),0)
}, unique(as.character(code$code))))
# code R1111 R1112 R1113 R1115
# 1 R1111 1 0 0 0
# 2 R1112 0 1 0 0
# 3 R1111 2 0 0 0
# 4 R1111 3 0 0 0
# 5 R1113 0 0 1 0
# 6 R1112 0 2 0 0
# 7 R1112 0 3 0 0
# 8 R1112 0 4 0 0
# 9 R1113 0 0 2 0
# 10 R1115 0 0 0 1
答案 1 :(得分:1)
您可以使用model.matrix
生成虚拟矩阵。然后将它乘以值的数量。
# calculate indicator using base or data.table, more succinctly
# code$tag = with(code, as.numeric(ave(as.character(code), code,
# FUN=function(x) cumsum(duplicated(x))+1L)))
code$tag = data.table::rowid(code$code)
model.matrix(~ 0 + code, data=code)* code$tag
# codeR1111 codeR1112 codeR1113 codeR1115
# 1 1 0 0 0
# 2 0 1 0 0
# 3 2 0 0 0
# 4 3 0 0 0
# 5 0 0 1 0
# 6 0 2 0 0
# 7 0 3 0 0
# 8 0 4 0 0
# 9 0 0 2 0
# 10 0 0 0 1
答案 2 :(得分:0)
基础R方法(它会抛出一些警告,你可以忽略它们):
x <- code$code
y <- rep(0, length(x))
DF <- data.frame(x, y, y, y, y)
DF[,2][DF[,1]==unique(x)[1]] <- 1:length(x)
DF[,3][DF[,1]==unique(x)[2]] <- 1:length(x)
DF[,4][DF[,1]==unique(x)[3]] <- 1:length(x)
DF[,5][DF[,1]==unique(x)[4]] <- 1:length(x)
如果你有很多要处理的列,请将它包装在循环中:
DF <- data.frame(x, y, y, y, y)
for(i in 1:4){
DF[,i+1][DF[,1]==unique(x)[i]] <- 1:length(x)
}
答案 3 :(得分:0)
sapply
能够执行此操作:我将code
存储为向量并执行一些后处理以生成实际的data.frame
。
code <- c("R1111", "R1112", "R1111", "R1111", "R1113", "R1112", "R1112",
"R1112", "R1113", "R1115")
val <- sapply(sort(unique(code)), function(thiscode)
(code==thiscode)*cumsum(code==thiscode)
)
输出是一个矩阵
R1111 R1112 R1113 R1115
[1,] 1 0 0 0
[2,] 0 1 0 0
[3,] 2 0 0 0
[4,] 3 0 0 0
[5,] 0 0 1 0
[6,] 0 2 0 0
[7,] 0 3 0 0
[8,] 0 4 0 0
[9,] 0 0 2 0
[10,] 0 0 0 1
然后格式化它会得到所需的输出。
val <- data.frame(code=code, val)
答案 4 :(得分:0)
一个相当简单的基础解决方案:
m <- sapply(unique(code$code),'==',code$code)
m2 <- apply(m,2,cumsum)
m2[!m] <- 0
cbind(code,`colnames<-`(m2,unique(code$code)))
# code R1111 R1112 R1113 R1115
# 1 R1111 1 0 0 0
# 2 R1112 0 1 0 0
# 3 R1111 2 0 0 0
# 4 R1111 3 0 0 0
# 5 R1113 0 0 1 0
# 6 R1112 0 2 0 0
# 7 R1112 0 3 0 0
# 8 R1112 0 4 0 0
# 9 R1113 0 0 2 0
# 10 R1115 0 0 0 1