按行计算发生率

时间:2015-12-04 13:23:14

标签: r count apply

想象一下,我有一个data.frame(或矩阵),其中包含很少的不同值,例如

test <- data.frame(replicate(10,sample(c(-1,0,1),20, replace=T, prob=c(0.2,0.2,0.6))))   
test2 <- test

如果我想添加额外的列,我可以这样做:

test2$good <-  apply(test,1, function(x) sum(x==1))   
test2$bad <-  apply(test,1, function(x) sum(x==-1)) 
test2$neutral <-  apply(test,1, function(x) sum(x==0))  

但是,如果我有许多可能的价值观,我将不得不创造许多线条,它不会优雅。

我已尝试使用table(),但输出不易使用

apply(test,1, function(x) table(x)) 

并且存在一个大问题,如果任何行不包含某些因素的任何后果,则table()生成的结果不具有相同的长度且不能被绑定。

有没有办法强制table()将该值考虑在内,告诉它没有出现?

然后我想到使用do.call或lapply并合并,但这对我来说太难了。

我也读过关于dplyr计数的内容,但我不知道如何做到这一点。 任何人都可以提供dplyr或tidyr的解决方案吗?

PD:data.table解决方案怎么样?

3 个答案:

答案 0 :(得分:3)

转换为melt后,我们可以matrix数据集进行长格式化,使用原始数据集使用tablecbind获取频率。

library(reshape2)
cbind(test2, as.data.frame.matrix(table(melt(as.matrix(test2))[-2]))) 

或者使用mtabulate对'test2'和cbind转置原始数据集。

library(qdapTools)
cbind(test2, mtabulate(as.data.frame(t(test2))))

我们可以在gather/spread

创建tidyr的行ID后,使用add_rownames中的dplyr
library(dplyr)
library(tidyr)
add_rownames(test2) %>%
     gather(Var, Val, -rowname) %>%\
     group_by(rn= as.numeric(rowname), Val) %>% 
     summarise(N=n()) %>%
     spread(Val, N, fill=0) %>%
     bind_cols(test2, .)

答案 1 :(得分:1)

您可以使用rowSums()

test2 <- cbind(test2, sapply(c(-1, 0, 1), function(x) rowSums(test==x)))

类似于etienne的评论中的代码,但未调用apply()

答案 2 :(得分:1)

以下是使用基础R的答案。

test <- data.frame(replicate(10,sample(c(-1,0,1),20, replace=T, prob=c(0.2,0.2,0.6))))   
testCopy <- test

# find all unique values, note that data frame is a list
uniqVal <- unique(unlist(test))

# the new column names start with Y
for (val in uniqVal) {
    test[paste0("Y",val)] <- apply(testCopy, 1, function(x) sum(x == val))
}

head(test)
#   X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 Y-1 Y1 Y0
# 1 -1  0  1  1  1  0 -1 -1  1   1   3  5  2
# 2  1 -1  0  1  1 -1 -1  0  0   1   3  4  3
# 3 -1  0  1  0  1  1  1  1 -1   1   2  6  2
# 4  1  1  1  1  0  1  1  0  1   0   0  7  3
# 5  0 -1  1 -1 -1  0  0  1  0   0   3  2  5
# 6  1  1  0  1  1  1  1  1  1   1   0  9  1