我正在使用R
中的大型数据框,但我接下来的行动,我的解决方案看起来太过分了。我将使用DF
作为我正在使用的数据帧的示例:
library(dplyr)
DF<-data.frame(ID=c(1:10),Cause1=c(rep("Yes 1",8),rep("No 1",2)),Cause2=c(rep("Yes 2",6),rep("No 2",4)),
Cause3=c(rep("Yes S",5),rep("No S",5)),Cause4=c(rep("Yes P",3),rep("No P",7)),
Cause5=c(rep("Yes",2),rep("No",8)),stringsAsFactors = F)
DF
具有下一个结构:
ID Cause1 Cause2 Cause3 Cause4 Cause5
1 1 Yes 1 Yes 2 Yes S Yes P Yes
2 2 Yes 1 Yes 2 Yes S Yes P Yes
3 3 Yes 1 Yes 2 Yes S Yes P No
4 4 Yes 1 Yes 2 Yes S No P No
5 5 Yes 1 Yes 2 Yes S No P No
6 6 Yes 1 Yes 2 No S No P No
7 7 Yes 1 No 2 No S No P No
8 8 Yes 1 No 2 No S No P No
9 9 No 1 No 2 No S No P No
10 10 No 1 No 2 No S No P No
其中DF
由六个变量组成(1个id变量,其他变量可以是Yes或No)。然后,对于具有前缀Cause
的每个变量,我需要计算该变量的摘要,作为第一步,之后我必须在实现它时过滤该变量(或者等于{ {1}})。例如,我将使用下一个代码及其相应的解释来完成此过程的第一阶段:
Yes
在这种情况下,使用#Filtering stage
#N1
DF %>% group_by(Cause1) %>% summarise(N=n()) -> d1
DF %>% filter(Cause1=="Yes 1") -> DF2
我按变量dplyr
和DF
对Cause1
进行分组,以计算其拥有的值的数量(summarise()
)。因此,结果将保存在n()
中。之后,我必须在d1
等于DF
时过滤Cause1
,并且必须将其保存在名为Yes 1
的新data.frame中。得到DF2
后,我必须为DF2
和Cause2, Cause3, Cause4
重复类似的例行程序。为此,我使用下一个代码:
Cause5
最终结果为#N2
DF2 %>% group_by(Cause2) %>% summarise(N=n()) -> d2
DF2 %>% filter(Cause2=="Yes 2") -> DF3
#N3
DF3 %>% group_by(Cause3) %>% summarise(N=n()) -> d3
DF3 %>% filter(Cause3=="Yes S") -> DF4
#N4
DF4 %>% group_by(Cause4) %>% summarise(N=n()) -> d4
DF4 %>% filter(Cause4=="Yes P") -> DF5
#N5
DF5 %>% group_by(Cause5) %>% summarise(N=n()) -> d5
DF5 %>% filter(Cause5=="Yes") -> DF6
,但我必须通过合并所有数据框DF6
和d1,d2,d3,d4
并过滤所有d5
值来进行控制。我用这个代码和那个porpouse。该代码为所有No
个数据框设置了通用名称,d's
数据框并过滤了rbind
模式。
No
我得到了这个:
#Connect
names(d1)<-names(d2)<-names(d3)<-names(d4)<-names(d5)<-c("Cause","N")
#Rbind
d<-rbind(d1,d2,d3,d4,d5)
d_reduced<-d[grepl("No",d$Cause),]
最后一步是计算 Cause N
1 No 1 2
2 No 2 2
3 No S 1
4 No P 2
5 No 1
中N
的总和和d_reduced
中的行数减去该值必须与{{1}的行数相同}}:
DF
在这种情况下,DF6
。
我想减少这么长的代码,因为在我的分析中,(dim(DF)[1]-sum(d_reduced$N))==dim(DF6)[1]
变量的数量可以增加,代码会更大。也许通过使用TRUE
策略或重塑数据可能会更好。任何有关降低代码级别的帮助都是不可思议的。提前谢谢。
答案 0 :(得分:0)
这样的事情怎么样?
首先,我们总结了多少&#34;否&#34;每个列都以&#34;原因&#34;:
开头num_no <- DF %>% summarise_each(funs(substr(., 1, 1) == "N"), starts_with("Cause"))
> num_no
Cause1 Cause2 Cause3 Cause4 Cause5
1 2 4 5 7 8
您对每个后续列之间的增量差异感兴趣,因此我们只需从num_no
中减去num_no
的滞后版本。
d_reduced <- num_no - lag(num_no, 1, 0)
> d_reduced
Cause1 Cause2 Cause3 Cause4 Cause5
1 2 2 1 2 1
这给出了你想要的值,但它们不是标记的,让我们解决这个问题,为每一列提取以N开头的唯一字符串:
labs <- lapply(DF, function(X){unique(X[grep("N", X)])}) %>% unlist
names(d_reduced) <- labs
> d_reduced
No 1 No 2 No S No P No
1 2 2 1 2 1
然后我们做最后一步,将d_reduced
的出现总和并从DF
的行数中减去那些,然后检查它是否等于&#的行数34:是&#34;他们的整个行。
> (nrow(DF) - sum(d_reduced)) == sum(DF[, ncol(DF)] == "Yes")
[1] TRUE
警告:这只会起作用,因为如果某人在最后一列中有“是”,则所有前面的列都是“是”(如您的示例中所示)。如果这个假设改变了,那么这个答案将不起作用。
答案 1 :(得分:0)
您可以重新构造为长格式,然后计算投票数,然后取得“是”值之间的差异。 data.table::melt
使用正则表达式来检测度量变量,这对于捕获所有Cause
变量非常有用。这有用吗?
d <-
melt(as.data.table(DF), # launch melt.data.table
id.vars = "ID",
measure.vars = patterns("Cause"), # grep columns
variable.name = "Cause") %>%
group_by(Cause) %>% # tabulate Yes's and No's
summarise(Yes = sum(grepl("Yes", value)),
No = sum(grepl("No", value))) %>%
mutate(N = lag(Yes) - Yes) %>% # N = difference between Yes's
rowwise() %>% # replace the NA in first row with the No value
mutate(N = replace(N, is.na(N), No))