我有一个如下所示的数据框:
a b c d
ab 0 0 1 0
cd -0.415 1.415 0 0
ef 0 0 0.0811 0.918
有没有一种简单的方法可以将此表转换为:
a b c d
ab 0 0 1 0
cd -0.415 0 0 0
cd 0 1.415 0 0
ef 0 0 0.0811 0
ef 0 0 0 0.918
如果原始表中有两个或更多个数字,我想将其转换为相应的行数。我还没有弄清楚如何做到这一点,所以任何帮助将不胜感激
答案 0 :(得分:4)
这是一种使用矩阵索引的方法。 (数据会变成一个矩阵,因此如果您的数据属于一种类型会更好,就像您的示例中的情况一样。)
reformat.dat <- function(dat) {
tdat <- t(dat)
nz <- tdat != 0
i <- col(tdat)[nz]
j <- row(tdat)[nz]
out <- matrix(0, sum(nz), ncol(dat))
out[cbind(seq_len(sum(nz)), j)] <- tdat[nz]
rownames(out) <- rownames(dat)[i]
colnames(out) <- colnames(dat)
out
}
reformat.dat(dat)
# a b c d
# ab 0.000 0.000 1.0000 0.000
# cd -0.415 0.000 0.0000 0.000
# cd 0.000 1.415 0.0000 0.000
# ef 0.000 0.000 0.0811 0.000
# ef 0.000 0.000 0.0000 0.918
答案 1 :(得分:4)
从@AnandaMahto借用一些并根据您的要求融化。请考虑:您想要检查的任何独特组合都在左侧〜变量的值在右侧。在这种情况下,变量名称变为值。
library(reshape2)
mydf <- structure(list(a = c(0, -0.415, 0), b = c(0, 1.415, 0),
c = c(1, 0, 0.0811), d = c(0, 0, 0.918)),
.Names = c("a", "b", "c", "d"),
class = "data.frame", row.names = c("ab", "cd", "ef"))
mydf$rows<- rownames(mydf)
m1<- melt(mydf, id="rows", measured= names(mydf))
m2<- dcast(m1, rows+value~..., fill=0)
m2<- m2[m2$value!=0, ]
m2$value <- NULL
#rows a b c d
#2 ab 0.000 0.000 1.0000 0.000
#3 cd -0.415 0.000 0.0000 0.000
#5 cd 0.000 1.415 0.0000 0.000
#7 ef 0.000 0.000 0.0811 0.000
#8 ef 0.000 0.000 0.0000 0.918
答案 2 :(得分:2)
以下是使用diag
:
o <- apply(df, 1, function(x) {
t <- diag(x)
colnames(t) <- names(x)
t <- t[rowSums(t == 0) != length(x), ,drop = FALSE]
t
})
ids <- rep(names(o), sapply(o, nrow))
o <- do.call(rbind, o)
row.names(o) <- ids
# a b c d
# ab 0.000 0.000 1.0000 0.000
# cd -0.415 0.000 0.0000 0.000
# cd 0.000 1.415 0.0000 0.000
# ef 0.000 0.000 0.0811 0.000
# ef 0.000 0.000 0.0000 0.918
这是matrix
。如果您需要as.data.frame(.)
,请使用data.frame
。
答案 3 :(得分:1)
这是一种方法,但您需要跟进修改行名称的一些修饰。
您的数据是以可复制的形式:
mydf <- structure(list(a = c(0, -0.415, 0), b = c(0, 1.415, 0),
c = c(1, 0, 0.0811), d = c(0, 0, 0.918)),
.Names = c("a", "b", "c", "d"),
class = "data.frame", row.names = c("ab", "cd", "ef"))
用NA
s替换零:
mydf[mydf == 0] <- NA
stack
您的data.frame
将其设为“长”data.frame
:
mydf1 <- data.frame(Rows = rownames(mydf), stack(mydf))
为“行”生成唯一值
mydf1$Rows <- make.unique(as.character(mydf1$Rows))
# Let's see what we have so far....
mydf1
# Rows values ind
# 1 ab NA a
# 2 cd -0.4150 a
# 3 ef NA a
# 4 ab.1 NA b
# 5 cd.1 1.4150 b
# 6 ef.1 NA b
# 7 ab.2 1.0000 c
# 8 cd.2 NA c
# 9 ef.2 0.0811 c
# 10 ab.3 NA d
# 11 cd.3 NA d
# 12 ef.3 0.9180 d
现在,只需使用xtabs
来获取您正在寻找的输出。如果您需要as.data.frame.matrix
,请将其包裹在data.frame
中,并在需要时清理行名称。
as.data.frame.matrix(xtabs(values ~ Rows + ind, mydf1))
# a b c d
# ab.2 0.000 0.000 1.0000 0.000
# cd -0.415 0.000 0.0000 0.000
# cd.1 0.000 1.415 0.0000 0.000
# ef.2 0.000 0.000 0.0811 0.000
# ef.3 0.000 0.000 0.0000 0.918
答案 4 :(得分:-1)
我认为你所要求的内容并不优雅,但也许你可以使用melt
中的reshape2
代替?它会为每行/每列提供一行:
> library(reshape2)
> # add row names as column
> df <- cbind(df, names=rownames(df))
> df <- melt(df,id.var="names")
Using as id variables
> df[df$value != 0,]
names variable value
2 cd a -0.4150
5 cd b 1.4150
7 ab c 1.0000
9 ef c 0.0811
12 ef d 0.9180