数据中的特殊出现计数 table
Special occurrency counting in data table
(序言)
我不知道这是否是正确的地方...我实际上有一个 solving/optimization 的问题,关于 table 的计数。所以如果不是。非常抱歉,值得负分。
这是数据框
dat <- data.frame(id=letters[1:5],matrix(c(0,0,1,0,0, 0,1,0,1,1, 0,0,2,1,0, 1,0,2,1,1, 0,0,2,0,0, 0,1,2,1,0),5,6))
#
# id X1 X2 X3 X4 X5 X6
# 1 a 0 0 0 1 0 0
# 2 b 0 1 0 0 0 1
# 3 c 1 0 2 2 2 2
# 4 d 0 1 1 1 0 1
# 5 e 0 1 0 1 0 0
我想沿着每一行数,有多少次到达 1,有多少次从 1 到 0。所以最后的结果应该是
# id N1 N0
# a 1 1
# b 2 1
# c 1 1
# d 2 1
# e 2 2
我实际上找到了一种算法,但它更 C/FORTRAN 风格(如下所示),我不敢相信在 R 中没有更简单、更优雅的方法。非常感谢您的帮助或暗示。
nr <- nrow(dat)
nc <- ncol(dat)
rownames(dat) <- seq(1,nr,1)
colnames(dat) <- seq(1,nc,1)
dat$N1 <- NULL
dat$N2 <- NULL
for (i in 1:nr) {
n1 <- 0
n0 <- 0
j <- 2
while (!(j>nc)) {
k <- j
if (dat[i,k] == 1) {
n1 <- n1 + 1
k <- j + 1
while (!(k>nc)) {
if (dat[i,k] == 0) {
n0 <- n0 + 1
break
}
k <- k + 1
}
}
j <- k
j <- j + 1
}
dat$N1[i] <- n1
dat$N0[i] <- n0
}
不确定我是否完全理解,但你可以试试:
cbind(dat["id"],N0=rowSums(dat[,3:7]==1 & dat[,2:6]!=1)+(dat[,2]==1),
N1=rowSums(dat[,3:7]==0 & dat[,2:6]==1))
# id N0 N1
#1 a 1 1
#2 b 2 1
#3 c 1 1
#4 d 2 1
#5 e 2 2
这是另一种方法,使用 data.table 语法中的 rle
:
library(data.table)
setDT(dat)
melt(dat, id="id")[, with(rle(value), list(
n1 = sum(values==1),
n1to0 = sum("10" == do.call(paste0, shift(values, 1:0, fill=0)))
)), by=id]
# id n1 n1to0
# 1: a 1 1
# 2: b 2 1
# 3: c 1 1
# 4: d 2 1
# 5: e 2 2
注释。
shift
和 n=1:0
returns 滞后向量(滞后 1)和向量本身(滞后 0)。
melt
创建一个 value
列; rle
包含一个 values
向量。
(序言) 我不知道这是否是正确的地方...我实际上有一个 solving/optimization 的问题,关于 table 的计数。所以如果不是。非常抱歉,值得负分。
这是数据框
dat <- data.frame(id=letters[1:5],matrix(c(0,0,1,0,0, 0,1,0,1,1, 0,0,2,1,0, 1,0,2,1,1, 0,0,2,0,0, 0,1,2,1,0),5,6))
#
# id X1 X2 X3 X4 X5 X6
# 1 a 0 0 0 1 0 0
# 2 b 0 1 0 0 0 1
# 3 c 1 0 2 2 2 2
# 4 d 0 1 1 1 0 1
# 5 e 0 1 0 1 0 0
我想沿着每一行数,有多少次到达 1,有多少次从 1 到 0。所以最后的结果应该是
# id N1 N0
# a 1 1
# b 2 1
# c 1 1
# d 2 1
# e 2 2
我实际上找到了一种算法,但它更 C/FORTRAN 风格(如下所示),我不敢相信在 R 中没有更简单、更优雅的方法。非常感谢您的帮助或暗示。
nr <- nrow(dat)
nc <- ncol(dat)
rownames(dat) <- seq(1,nr,1)
colnames(dat) <- seq(1,nc,1)
dat$N1 <- NULL
dat$N2 <- NULL
for (i in 1:nr) {
n1 <- 0
n0 <- 0
j <- 2
while (!(j>nc)) {
k <- j
if (dat[i,k] == 1) {
n1 <- n1 + 1
k <- j + 1
while (!(k>nc)) {
if (dat[i,k] == 0) {
n0 <- n0 + 1
break
}
k <- k + 1
}
}
j <- k
j <- j + 1
}
dat$N1[i] <- n1
dat$N0[i] <- n0
}
不确定我是否完全理解,但你可以试试:
cbind(dat["id"],N0=rowSums(dat[,3:7]==1 & dat[,2:6]!=1)+(dat[,2]==1),
N1=rowSums(dat[,3:7]==0 & dat[,2:6]==1))
# id N0 N1
#1 a 1 1
#2 b 2 1
#3 c 1 1
#4 d 2 1
#5 e 2 2
这是另一种方法,使用 data.table 语法中的 rle
:
library(data.table)
setDT(dat)
melt(dat, id="id")[, with(rle(value), list(
n1 = sum(values==1),
n1to0 = sum("10" == do.call(paste0, shift(values, 1:0, fill=0)))
)), by=id]
# id n1 n1to0
# 1: a 1 1
# 2: b 2 1
# 3: c 1 1
# 4: d 2 1
# 5: e 2 2
注释。
shift
和n=1:0
returns 滞后向量(滞后 1)和向量本身(滞后 0)。melt
创建一个value
列;rle
包含一个values
向量。