【问题标题】:Identify duplicates of one value with different values in another column识别另一列中具有不同值的一个值的重复项
【发布时间】:2018-04-11 05:57:00
【问题描述】:

我有一个 ID 和地址的数据框。通常,我希望每个重复出现的 ID 在所有观察中都具有相同的地址,但我的一些 ID 具有不同的地址。我想找到那些在 ID 上重复但至少有 2 个不同地址的观察结果。然后,我想为其中一个随机化一个新 ID(之前在 DF 中不存在的 ID)。

例如:

ID     Address
1      X
1      X  
1      Y
2      Z
2      Z
3      A
3      B
4      C
4      D
4      E
5      F
5      F
5      F

将返回:

ID    Address
1      X
1      X  
6      Y
2      Z
2      Z
3      A
7      B
4      C
8      D
9      E
5      F
5      F
5      F

所以发生的事情是第 3、7、9 和 10 次观察得到了新的 ID。我会提到,一个 ID 可能有超过 2 个不同的地址,因此应该为每个唯一地址授予新 ID。

编辑:

我为更长的数据框示例添加了代码,其中 rand 列应该被忽略但保留在最终输出中。

df <- data.frame(ID = c(1,1,1,2,2,3,3,4,4,4,5,5,5),
             Address = c("x","x","y","z","z","a","b","c","d","e",
                         "f","f","f"),
             rand = sample(1:100, 13))

【问题讨论】:

  • 你能提供你的代码吗?
  • 用于创建示例数据框?
  • 基于新的数据集,预期的输出是什么?
  • 在问题中添加了更长的示例和更长的结果

标签: r duplicates unique


【解决方案1】:

这是tidyr 和函数nest / unnest 的解决方案

library(tidyr)
library(dplyr)
df %>% group_by(ID,Address) %>% nest %>%
  `[<-`(duplicated(.$ID),"ID",max(.$ID, na.rm = TRUE) + 1:sum(duplicated(.$ID))) %>%
  unnest

# # A tibble: 13 x 3
# ID Address  rand
#    <dbl>  <fctr> <int>
#  1     1       x    58
#  2     1       x     4
#  3     6       y    75
#  4     2       z     5
#  5     2       z    19
#  6     3       a    55
#  7     7       b    34
#  8     4       c    53
#  9     8       d    98
# 10     9       e    97
# 11     5       f    13
# 12     5       f    64
# 13     5       f    80

如果您使用magrittr,如果您想要更漂亮的代码(相同的输出),请将[&lt;- 替换为inset

【讨论】:

  • 这看起来很紧凑,但是我在复制它时遇到了一些问题。您使用的是哪个版本的 tidyr?
  • 我用数据和包版本更新了答案,你有什么错误?
  • 我有 0.7.1 版本,我得到 Error in [(., duplicated(.$ID), "ID", max(.$ID) + 1:sum(duplicated(.$ID))) : replacement has 2 rows, data has 1 In addition: Warning messages: 1: Unknown or uninitialised column: 'ID'. 2: Unknown or uninitialised column: 'ID'. 3: In max(.$ID) : no non-missing arguments to max; returning -Inf 4: Unknown or uninitialised column: 'ID'.
  • 查看更新的解决方案,适用于最新的 dplyr 和您更新的示例
  • 我相信 nest 过去默认使用 group_by 所有列,如果表没有分组,现在它根本不分组,你将所有表分组到一个元素中
【解决方案2】:

一个选项是data.table。按'ID'分组后,ifunique'Address'的个数大于1且'Address'不等于第一个unique'Address',则得到行索引(.I ) 并将那些“ID”分配给原始数据集中尚不存在的“ID”

library(data.table)
i1 <- setDT(df)[,  .I[if(uniqueN(Address)>1) Address != unique(Address)[1]], ID]$V1
df[i1, ID := head(setdiff(as.numeric(1:10), unique(df$ID)), length(i1))] 
df
#     ID Address rand
#  1:  1       x   58
#  2:  1       x    4
#  3:  6       y   75
#  4:  2       z    5
#  5:  2       z   19
#  6:  3       a   55
#  7:  7       b   34
#  8:  4       c   53
#  9:  8       d   98
# 10:  9       e   97
# 11:  5       f   13
# 12:  5       f   64
# 13:  5       f   80

或者我们可以使用base R

ids <- names(which(rowSums(table(unique(df)))>1))
i2 <- with(df, ID %in% ids & Address != ave(as.character(Address), 
                     ID, FUN = function(x) x[1]))
df$ID[i2] <- head(setdiff(1:10, unique(df$ID)), sum(i2))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多