创建重复ID /键的映射表

时间:2017-08-03 13:17:37

标签: r dataframe duplicates data.table dplyr

我确实有一个统计例程,它不喜欢行精确重复(没有ID)导致空距离。

所以我首先检测我删除的重复项,应用我的例程并将剩下的记录合并。

为简单起见,请考虑使用rownames作为ID /密钥。

我找到了以下方式在基础R中实现我的结果:

data <- data.frame(x=c(1,1,1,2,2,3),y=c(1,1,1,4,4,3))

# check duplicates and get their ID -- cf. https://stackoverflow.com/questions/12495345/find-indices-of-duplicated-rows
dup1 <- duplicated(data)
dupID <- rownames(data)[dup1 | duplicated(data[nrow(data):1, ])[nrow(data):1]]

# keep only those records that do have duplicates to preveng running folowing steps on all rows
datadup <- data[dupID,]

# "hash" row
rowhash <- apply(datadup, 1, paste, collapse="_")

idmaps <- split(rownames(datadup),rowhash)
idmaptable <- do.call("rbind",lapply(idmaps,function(vec)data.frame(mappedid=vec[1],otherids=vec[-1],stringsAsFactors = FALSE)))

这给了我想要的东西,即重复数据删除数据(简单)和映射表。

> (data <- data[!dup1,])
  x y
1 1 1
4 2 4
6 3 3
> idmaptable
      mappedid otherids
1_1.1        1        2
1_1.2        1        3
2_4          4        5

我想知道是否有更简单或更有效的方法(data.table / dplyr已被接受)。建议的其他选择吗?

3 个答案:

答案 0 :(得分:4)

使用data.table ...

library(data.table)
setDT(data)

# tag groups of dupes
data[, g := .GRP, by=x:y]

# do whatever analysis
f = function(DT) Reduce(`+`, DT)
resDT = unique(data, by="g")[, res := f(.SD), .SDcols = x:y][]

# "update join" the results back to the main table if needed
data[resDT, on=.(g), res := i.res ]

OP跳过了示例的中心部分(使用重复数据删除的数据),所以我只是编造了f

答案 1 :(得分:1)

使用tidyverse的解决方案。我通常不会在行名称中存储信息,因此我创建了IDID2来存储信息。但是,当然,您可以根据自己的需要进行更改。

library(tidyverse)

idmaptable <- data %>%
  rowid_to_column() %>%
  group_by(x, y) %>%
  filter(n() > 1) %>%
  unite(ID, x, y) %>%
  mutate(ID2 = 1:n()) %>%
  group_by(ID) %>%
  mutate(ID_type = ifelse(row_number() == 1, "mappedid", "otherids")) %>%
  spread(ID_type, rowid) %>%
  fill(mappedid) %>%
  drop_na(otherids) %>%
  mutate(ID2 = 1:n())

idmaptable
# A tibble: 3 x 4
# Groups:   ID [2]
     ID   ID2 mappedid otherids
  <chr> <int>    <int>    <int>
1   1_1     1        1        2
2   1_1     2        1        3
3   2_4     1        4        5

答案 2 :(得分:1)

对基础R解决方案进行了一些改进,

select *
, case when value1>=65 and min(value2) over (partition by site_id, sector_id)<25 then 'LOW_LOAD_CELL' end cell_status 
from your_table

由此给出,

df <- data[duplicated(data)|duplicated(data, fromLast = TRUE),]

do.call(rbind, lapply(split(rownames(df), 
               do.call(paste, c(df, sep = '_'))), function(i) 
                                                  data.frame(mapped = i[1], 
                                                             others = i[-1], 
                                                             stringsAsFactors = FALSE)))

当然,

     mapped others
1_1.1      1      2
1_1.2      1      3
2_4        4      5
相关问题