我想在数据框中识别(不消除)重复项,并使用R dplyr
包相应地添加0/1变量(一行是否重复)。
示例:
| A B C D
1 | 1 0 1 1
2 | 1 0 1 1
3 | 0 1 1 1
4 | 0 1 1 1
5 | 1 1 1 1
显然,第1行和第2行是重复的,所以我想创建一个新的变量(mutate
?),比如E
,在行1,2,3中等于1,因为第3行和第4行也是相同的。
此外,我想添加另一个变量F
,如果只有一个副本存在重复,则该变量等于1。也就是说,第1,2和5行中的F
将等于1,因为它们仅在B
列中有所不同。
我希望很清楚我想做什么,我希望dplyr能够顺利解决这个问题。这当然可以在“基础”R中使用,但我相信(希望)存在更平滑的解决方案。
答案 0 :(得分:1)
您可以使用=COUNTIFS($A:$A,$A1,$B:$B,$B1,$C:$C,"Apple",$C:$C,$C1)>1
来计算差异,然后在生成的距离对象中搜索可以提供所需的答案(E,F等)。以下是一个示例代码,其中dist()
是原始X
:
data.frame
只需更改W=as.matrix(dist(X, method="manhattan"))
X$E = as.integer(sapply(1:ncol(W), function(i,D){any(W[-i,i]==D)}, D=0))
X$F = as.integer(sapply(1:ncol(W), function(i,D){any(W[-i,i]==D)}, D=1))
所需的不同列数即可。
它虽然都是基地。使用D=
代替plyr::laply
具有相同的效果。 sappy
在这里看起来有点过头了。
答案 1 :(得分:0)
这是一个data.table
解决方案,可扩展到任意情况(1..n列相同) - 不确定是否有人可以为您转换为dpylr
。我不得不稍微改变你的数据集以显示你想要的F列 - 在你的例子中,所有行都会得到1,因为3和4也是一列不同于5。
library(data.table)
DT <- data.frame(A = c(1,1,0,0,1), B = c(0,0,1,1,1), C = c(1,1,1,1,1), D = c(1,1,1,1,1), E = c(1,1,0,0,0))
DT
A B C D E
1 1 0 1 1 1
2 1 0 1 1 1
3 0 1 1 1 0
4 0 1 1 1 0
5 1 1 1 1 0
setDT(DT)
DT_ncols <- length(DT)
base <- data.table(t(combn(1:nrow(DT), 2)))
setnames(base, c("V1","V2"),c("ind_x","ind_y"))
DT[, ind := .I)]
DT_melt <- melt(DT, id.var = "ind", variable.name = "column")
base <- merge(base, DT_melt, by.x = "ind_x", by.y = "ind", allow.cartesian = TRUE)
base <- merge(base, DT_melt, by.x = c("ind_y", "column"), by.y = c("ind", "column"))
base <- base[, .(common_cols = sum(value.x == value.y)), by = .(ind_x, ind_y)]
这为我们提供了一个如下所示的data.frame:
base
ind_x ind_y common_cols
1: 1 2 5
2: 1 3 2
3: 2 3 2
4: 1 4 2
5: 2 4 2
6: 3 4 5
7: 1 5 3
8: 2 5 3
9: 3 5 4
10: 4 5 4
这表示第1行和第2行有5个公共列(重复)。第3行和第5行有4个公共列,4和5有4个公共列。我们现在可以使用相当可扩展的格式来标记我们想要的任何组合:
base <- melt(base, id.vars = "common_cols")
# Unique - common_cols == DT_ncols
DT[, F := ifelse(ind %in% unique(base[common_cols == DT_ncols, value]), 1, 0)]
# Same save 1 - common_cols == DT_ncols - 1
DT[, G := ifelse(ind %in% unique(base[common_cols == DT_ncols - 1, value]), 1, 0)]
# Same save 2 - common_cols == DT_ncols - 2
DT[, H := ifelse(ind %in% unique(base[common_cols == DT_ncols - 2, value]), 1, 0)]
这给出了:
A B C D E ind F G H
1: 1 0 1 1 1 1 1 0 1
2: 1 0 1 1 1 2 1 0 1
3: 0 1 1 1 0 3 1 1 0
4: 0 1 1 1 0 4 1 1 0
5: 1 1 1 1 0 5 0 1 1
您可以附加所有组合,而不是手动选择:
# run after base <- melt(base, id.vars = "common_cols")
base <- unique(base[,.(ind = value, common_cols)])
base[, common_cols := factor(common_cols, 1:DT_ncols)]
merge(DT, dcast(base, ind ~ common_cols, fun.aggregate = length, drop = FALSE), by = "ind")
ind A B C D E 1 2 3 4 5
1: 1 1 0 1 1 1 0 1 1 0 1
2: 2 1 0 1 1 1 0 1 1 0 1
3: 3 0 1 1 1 0 0 1 0 1 1
4: 4 0 1 1 1 0 0 1 0 1 1
5: 5 1 1 1 1 0 0 0 1 1 0
答案 2 :(得分:0)
这是一个dplyr解决方案:
test%>%mutate(flag = (A==lag(A)&
B==lag(B)&
C==lag(C)&
D==lag(D)))%>%
mutate(twice = lead(flag)==T)%>%
mutate(E = ifelse(flag == T | twice ==T,1,0))%>%
mutate(E = ifelse(is.na(E),0,1))%>%
mutate(FF = ifelse( ( (A +lag(A)) + (B +lag(B)) + (C+lag(C)) + (D + lag(D))) == 7,1,0))%>%
mutate(FF = ifelse(is.na(FF)| FF == 0,0,1))%>%
select(A,B,C,D,E,FF)
结果:
A B C D E FF
1 1 0 1 1 1 0
2 1 0 1 1 1 0
3 0 1 1 1 1 0
4 0 1 1 1 1 0
5 1 1 1 1 0 1