使用`dplyr`

时间:2018-01-25 10:13:48

标签: r dplyr

我想在数据框中识别(不消除)重复项,并使用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中使用,但我相信(希望)存在更平滑的解决方案。

3 个答案:

答案 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