【问题标题】:Efficiently find groups of rows in a data frame with almost identical values有效地在数据框中找到具有几乎相同值的行组
【发布时间】:2020-07-13 10:30:45
【问题描述】:

我有一个大约一千行的数据集,但它会增长。 我想找到一定数量的属性几乎相同的行组。

我可以做一个愚蠢的蛮力搜索,但它真的很慢,我相信 R 可以做得更好。

测试数据:

df = read.table(text="
      Date     Time  F1   F2   F3   F4   F5 Conc
2010-06-23 04:00:00 0.1 17.6 14.2 19.5 18.6 16.1
2010-12-16 00:20:00 0.0 28.7 13.7 15.6 16.2 14.4
2010-12-16 10:30:00 0.0 17.0 14.0 19.0 18.0 16.0
2010-12-16 22:15:00 0.0 25.5 12.6 14.9 16.6 16.8
", header=T)


#Initialize column to hold clustering info
df$cluster = NA

#Maximum tolerance for a match between rows 
toler=1.0

#Brute force search, very ugly.
for(i in 1:(nrow(df)-1)){
    if(is.na(df$cluster[i])){
        df$cluster[i] <- i
        for(j in (i+1):nrow(df)){
            if(max(abs(df[i,3:7] - df[j,3:7]))<toler){
                df$cluster[j]<-i
            }
        }
    }
}
if(is.na(df$cluster[j])){df$cluster[j] <- j}

df

预期输出:

        Date     Time  F1   F2   F3   F4   F5 Conc cluster
1 2010-06-23 04:00:00 0.1 17.6 14.2 19.5 18.6 16.1       1
2 2010-12-16 00:20:00 0.0 28.7 13.7 15.6 16.2 14.4       2
3 2010-12-16 10:30:00 0.0 17.0 14.0 19.0 18.0 16.0       1
4 2010-12-16 22:15:00 0.0 25.5 12.6 14.9 16.6 16.8       4

【问题讨论】:

    标签: r pattern-matching


    【解决方案1】:

    这是一个使用data.table的选项:

    df[, (cols) := c(.SD-1, .SD+1), .SDcols=fcols]
    onstr <- c(paste0(fcols,">",cols[rng]),paste0(fcols,"<",cols[5+rng]))
    df[, cluster := df[df, on=onstr, by=.EACHI, min(x.rn)]$V1]
    

    输出:

             Date     Time  F1   F2   F3   F4   F5 Conc rn lower1 lower2 lower3 lower4 lower5 upper1 upper2 upper3 upper4 upper5 cluster
    1: 2010-06-23 04:00:00 0.1 17.6 14.2 19.5 18.6 16.1  1   -0.9   16.6   13.2   18.5   17.6    1.1   18.6   15.2   20.5   19.6       1
    2: 2010-12-16 00:20:00 0.0 28.7 13.7 15.6 16.2 14.4  2   -1.0   27.7   12.7   14.6   15.2    1.0   29.7   14.7   16.6   17.2       2
    3: 2010-12-16 10:30:00 0.0 17.0 14.0 19.0 18.0 16.0  3   -1.0   16.0   13.0   18.0   17.0    1.0   18.0   15.0   20.0   19.0       1
    4: 2010-12-16 22:15:00 0.0 25.5 12.6 14.9 16.6 16.8  4   -1.0   24.5   11.6   13.9   15.6    1.0   26.5   13.6   15.9   17.6       4
    

    数据:

    df = read.table(text="
          Date     Time  F1   F2   F3   F4   F5 Conc
    2010-06-23 04:00:00 0.1 17.6 14.2 19.5 18.6 16.1
    2010-12-16 00:20:00 0.0 28.7 13.7 15.6 16.2 14.4
    2010-12-16 10:30:00 0.0 17.0 14.0 19.0 18.0 16.0
    2010-12-16 22:15:00 0.0 25.5 12.6 14.9 16.6 16.8
    ", header=T)
    
    library(data.table)
    setDT(df)[, rn := .I]
    toler <- 1.0
    rng <- 1L:5L
    fcols <- paste0("F", rng)
    cols <- do.call(paste0, CJ(c("lower", "upper"), rng))
    

    解释:

    • L 在一个整数后面告诉 R 这是整数类型(参见Why would R use the "L" suffix to denote an integer?

    • df[df, on=onstr, by=.EACHI, min(x.rn)] 正在使用onstr 中指定的不等式执行非等自连接。

    • $V1访问上述join的V1列(不提供时默认命名为V*)

    • df[, cluster := my_result] 通过引用更新原始 data.table 以便在数据集较大时更快。改进是由于不需要像在基础 R 中那样对原始 data.frame 进行深层复制。

    • 由于我们正在执行连接,因此存在左表和右表。在data.table 术语中,对于x[i, on=join_keys]x 是右表,i 是左表(灵感来自基本 R 语法)。因此,x. 用于引用左表中的访问列,就像 SQL 语法一样,i. 也类似。可以在 data.table 小插图中找到更多详细信息。 (见https://cran.r-project.org/web/packages/data.table/

    【讨论】:

    • @Community,请删除以上评论。
    猜你喜欢
    • 1970-01-01
    • 2013-07-24
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    相关资源
    最近更新 更多