【问题标题】:Duplicate combination of values in columns列中值的重复组合
【发布时间】:2015-11-26 13:18:34
【问题描述】:

类似于this question,我有一个数据框,想提取几个特定列中的值组合不唯一的行。

例如,我有一个数据框 df:

> df<-data.frame(c(1,2,3,4),c(T,F,T,T),c("a","b","c","b"),c("b","d","e","a"))
> df
     [,1] [,2]    [,3] [,4]
[1,] "1"  "TRUE"  "a"  "b" 
[2,] "2"  "FALSE" "b"  "d" 
[3,] "3"  "TRUE"  "c"  "e" 
[4,] "4"  "TRUE"  "b"  "a" 

我想测试第 2、3 和 4 列中的值组合对于数据框的行是唯一的还是重复的。但是,我不想将第一次出现的组合归类为唯一组合,并将所有后续组合归类为重复组合,而是将所有出现的非唯一组合归为重复组合。

在此示例中,第 1 行和第 4 行是重复的,第 2 行和第 3 行在第 2、3 和 4 列中的值组合中是唯一的。

任何帮助将不胜感激。

【问题讨论】:

  • 你的 data.frame 是一个矩阵。使用data.frame 而不是cbind 创建data.frame。

标签: r dataframe


【解决方案1】:

使用 dplyr 的另一种方法。它使用行的所有组合并检查一行的所有元素是否属于另一行。最后,您得到的不是 True/False,而是每行的一个数字,表示它与其他行匹配的次数。一步一步运行脚本会更明显。

df<-data.frame(x1 =c(1,2,3,4),
               x2 = c(T,F,T,T),
               x3 = c("a","b","c","b"),
               x4 = c("b","d","e","a"), stringsAsFactors = F)

library(dplyr)


df %>%                                                                                
  rowwise() %>%                                                                     # for each row
  do(data.frame(., df2=df, stringsAsFactors=F)) %>%                                 # combine each row with all rows of dataset
  filter(x1 != df2.x1) %>%                                                          # exclude cases of self combinations
  rowwise() %>%                                                                     # for each row combination
  mutate(match = 
           ifelse(sum(c(x2,x3,x4) %in% c(df2.x2, df2.x3, df2.x4))==3, 1, 0)) %>%    # flag a match when all 3 elements of one row belong to the elements of the other row 
  group_by(x1,x2,x3,x4) %>%                                                         # group by rows of initial dataset
  summarise(sum_match = sum(match)) %>%                                             # calculate how many times they match with other rows
  ungroup


#   x1    x2 x3 x4 sum_match
# 1  1  TRUE  a  b         1
# 2  2 FALSE  b  d         0
# 3  3  TRUE  c  e         0
# 4  4  TRUE  b  a         1

【讨论】:

    【解决方案2】:

    我们 sort 使用 apply 和 MARGIN=1 按行在“df”中的列 3:4,转置 (t) 并将输出分配给相应的列。要获取所有重复项的逻辑索引,我们可以使用fromLast=TRUE 在默认方向和反向应用duplicated。在这里,我假设第一列不会用于考虑重复元素。

    df[3:4] <- t(apply(df[3:4], 1, sort))
    duplicated(df[-1])|duplicated(df[-1], fromLast=TRUE)
    #[1]  TRUE FALSE FALSE  TRUE
    

    【讨论】:

    • 谢谢,它可以工作,但我不得不摆脱重新分配第 3 列和第 4 列以保持我的数据框处于当前形式。
    • @atreju 在这种情况下,您可以创建一个新的数据框,然后执行重复的dfN &lt;- cbind(df[2],t(apply(df[3:4], 1, sort))); duplicated(dfN)|duplicated(dfN, fromLast=TRUE)
    猜你喜欢
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 2018-05-15
    相关资源
    最近更新 更多