我试图检查data.table中的每一行是否存在某些元素(如果存在,我会声明为1)。如果有,我想输出一个新列,显示从另一个data.table引用的值(元素发生的概率)。
这是输入
structure(list(A = c(0L, 0L, 0L, 0L, 0L), B = c(0L, 0L, 0L, 0L,
0L), C = c(1L, 0L, 1L, 1L, 1L), D = c(0L, 1L, 0L, 0L, 1L)), .Names = c("A",
"B", "C", "D"), class = "data.frame", row.names = c(NA, -5L))
我过去用来引用概率的表
表Pyxixj
A B C D
A 0 0 0 0
B 0 0 0 0
C 0 0 0 0.001804403
D 0 0 0.001804403 0
表Pyxi
A 0
B 0
C 0.00086701
D 0.000250439
这是输出
A B C D prob
1 0 0 1 0 0.00086701
2 0 0 0 1 0.000250439
3 0 0 1 0 0.00086701
4 0 0 1 0 0.00086701
5 0 0 1 1 0.001804403
我使用下面的for循环完成了它,但运行大约100万行需要6小时。
for (i in 1:nrow(cnts2))
{
if ((rowSums(cnts2 == "1", na.rm = TRUE) == 1)[i])
{
cnts2$prob[i] <- Pyxi[colnames(cnts2)[which(cnts2[i, ] == 1)]]
}
else
{
cnts2$prob[i] <- Pyxixj[colnames(cnts2)[which(cnts2[i, ] == 1)][1], colnames(cnts2)[which(cnts2[i, ] == 1)][2]]
}
}
一直在尝试apply
,但我已经弄明白了。
答案 0 :(得分:0)
这是一个更快但可能需要更多ram的解决方案,因为它会创建一些非常长的数据帧,我创建了一个不同的Pyxixj数据帧,因为我的解决方案不需要另一个表。
此解决方案的关键是将cnts2数据框更改为可以保持概率连接的形式,从而消除对循环或lapply的任何需求
library(dplyr);library(tidyr)
#probability data frame note use of X1
Pyxixj <- data.frame(X1=c("A", "B", "C", "D"),
matrix(data=sample(1:100, 16, replace=TRUE)/100, nrow= 4) ) %>%
setNames(c("X1", "A", "B", "C", "D"))
#Restructure the initial data frame
probmerge <-cnts2 %>%mutate(rowid= 1:nrow(.)) %>%
gather(., key=column, value=yesno,-rowid) %>%
filter(yesno==1) %>% group_by(rowid) %>%
mutate(order=make.names(cumsum(yesno))) %>%
spread(key=order, value=column) %>%
mutate(X2=ifelse(is.na(X2),X1,X2)) %>%ungroup
#Gather your probability dataframe
Pyxixj <-Pyxixj %>% gather(key="X2", value=prob,-X1)
#join the two new dataframes
probmerge<-left_join(probmerge, Pyxixj, by=c("X1", "X2"))
#bind onto the orignial dataframe
cnts2 <- bind_cols(cnts2, select(probmerge, prob))
答案 1 :(得分:0)
您可以从for循环中移除表格Pyxi的查找以更快地循环
这在查找Pyxi
时使用了R的函数应用矢量化 if (rowSums(cnts2 == "1", na.rm = TRUE) == 1)
{
cnts2$probs <- (Pyxi[rownames(Pyxi)=="A"]*cnts2$A
+ Pyxi[rownames(Pyxi)=="B"]*cnts2$B
+ Pyxi[rownames(Pyxi)=="C"]*cnts2$C
+ Pyxi[rownames(Pyxi)=="D"]*cnts2$D)
}
然后在行计数> 1
的地方进行循环for (i in 1:nrow(cnts2))
{
if ((rowSums(cnts2 == "1", na.rm = TRUE) > 1)[i])
{cnts2$prob[i] <- Pyxixj[colnames(cnts2)[which(cnts2[i, ] == 1)][1],
colnames(cnts2)[which(cnts2[i, ] == 1)][2]]
}
}