在数据框中高效地查找具有几乎相同值的行组
Efficiently find groups of rows in a data frame with almost identical values
我有大约一千行的数据集,但它会增长。
我想找到一定数量的属性几乎相同的行组。
我可以做一个愚蠢的暴力搜索,但它真的很慢,我相信 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
这是一个使用 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 进行深度复制。
因为我们正在执行连接,所以有左 table 和右 table。在 data.table
术语中,对于 x[i, on=join_keys]
,x
是右 table,i
是左 table(灵感来自基础 R 语法)。因此,x.
用于引用左侧 table 中的访问列,类似于 SQL 语法,类似地用于 i.
。可以在 data.table 小插图中找到更多详细信息。 (参见 https://cran.r-project.org/web/packages/data.table/)
我有大约一千行的数据集,但它会增长。 我想找到一定数量的属性几乎相同的行组。
我可以做一个愚蠢的暴力搜索,但它真的很慢,我相信 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
这是一个使用 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 进行深度复制。因为我们正在执行连接,所以有左 table 和右 table。在
data.table
术语中,对于x[i, on=join_keys]
,x
是右 table,i
是左 table(灵感来自基础 R 语法)。因此,x.
用于引用左侧 table 中的访问列,类似于 SQL 语法,类似地用于i.
。可以在 data.table 小插图中找到更多详细信息。 (参见 https://cran.r-project.org/web/packages/data.table/)