r - 将数据帧子集到 R 中的“最佳正方形”的函数
问题描述
我的目标是在 R 中编写一个函数,该函数将数据框作为输入并返回它的“最佳平方子集”。
通过最佳平方子集,我的意思是输出需要确认以下内容:
- 所有单元格/元素均高于 2000
- 它有尽可能多的细胞/元素
- 如果出现平局(符合上述标准并包含相同单元数的 2 个数据框),则返回单元格/元素总和最高的那个
让我们举以下三个例子:
example1 <- structure(list(Afternoon = c(20800L, 15254L, 17426L, 4391L, 39194L
), Evening = c(21679L, 0L, 2973L, 37L, 435L), Morning = c(0L,
3726L, 0L, 0L, 0L)), .Names = c("Afternoon", "Evening", "Morning"
), row.names = c("Friday", "Monday", "Thursday", "Tuesday", "Wednesday"
), class = "data.frame")
example2 <- structure(list(Afternoon = c(1227364L, 219402L, 3L, 0L, 530891L,
153124L, 281788L), Evening = c(570618L, 167216L, 31L, 10L, 88702L,
161006L, 42L), Morning = c(0L, 121775L, 0L, 0L, 0L, 25133L, 270162L
)), .Names = c("Afternoon", "Evening", "Morning"), row.names = c("Friday",
"Monday", "Saturday", "Sunday", "Thursday", "Tuesday", "Wednesday"
), class = "data.frame")
example3 <- structure(list(Afternoon = c(20800L, 258L, 300L, 563L, 2000L
), Evening = c(21679L, 0L, 2973L, 37L, 435L), Morning = c(0L,
3726L, 0L, 0L, 0L)), .Names = c("Afternoon", "Evening", "Morning"
), row.names = c("Friday", "Monday", "Thursday", "Tuesday", "Wednesday"
), class = "data.frame")
看起来像这样:
> example1
Afternoon Evening Morning
Friday 20800 21679 0
Monday 15254 0 3726
Thursday 17426 2973 0
Tuesday 4391 37 0
Wednesday 39194 435 0
> example2
Afternoon Evening Morning
Friday 1227364 570618 0
Monday 219402 167216 121775
Saturday 3 31 0
Sunday 0 10 0
Thursday 530891 88702 0
Tuesday 153124 161006 25133
Wednesday 281788 42 270162
> example3
Afternoon Evening Morning
Friday 20800 21679 0
Monday 258 0 3726
Thursday 300 2973 0
Tuesday 563 37 0
Wednesday 2000 435 0
我正在寻找的函数应将上述 3 个示例分别子集为以下 3 个:
> output1
Afternoon
Friday 20800
Monday 15254
Thursday 17426
Tuesday 4391
Wednesday 39194
正方形的分数/面积是 5。其他任何东西都会更少。例如,选择 Friday,Thursday Afternoon 晚上会得到 4 分
> output2
Afternoon Evening
Friday 1227364 570618
Monday 219402 167216
Thursday 530891 88702
Tuesday 153124 161006
在这里,有人首先想到的是选择所有星期一、星期二和星期三的时间并得到 9 分。但是,Wendesday nights 的 42 验证了第一个标准。周一和周二所有日期和时间将产生 6 分/面积
> output3
Afternoon Evening
Friday 20800 21679
在这里,我们有两个可能的方格来验证前 2 个标准:周五下午和晚上或周五和周三下午。我们必须选择第一种,因为单元格内的总和高于第二种情况。此规则仅适用于平局。
解决方案
最直观的解决方案是遍历所有可能的行和列组合,并检查选定的行和列是否形成一个完整的正方形,如果是,则检查它是否形成了可能的最大数。这种方法的一个潜在问题是,如果您有很多列和行,则需要很长时间才能完成,这不是最佳的。当列数和行数不大于 12 时,我对此处出现的问题的回答工作得相当好(在我的 PC 上,配备 16GB RAM、2.7 GHz CPU 和 Windows 10pro 64 位,R 版本 3.5.1)。
#library(gtools)
find_best_square <- function(x, thresh = 2000){
# x <- example1
x[x<thresh] <- 0
# for larger datasets only: removing lonely cells
if (ncol(x) > 7 | nrow(x)> 7){
for (i in 1:nrow(x)){
for (j in 1:ncol(x)){
if((colSums(x[,j,drop=F]) == x[i,j]) & (rowSums(x[i,,drop=F])==x[i,j])) x[i, j] <- 0L
}
}
}
# remove columns with no data
is_colZero <- colSums(x==0)== nrow(x)
if(any(is_colZero)) print(paste('this column is empty and removed: ', which(is_colZero)))
x <- x[,!is_colZero]
# remove rows with no data
is_rowZero <- rowSums(x==0)==ncol(x)
if(any(is_rowZero)) print(paste('this row is empty and removed: ', which(is_rowZero)))
x <- x[!is_rowZero,]
n <- ncol(x)
m <- nrow(x)
max_size <- 0L
max_sum <- 0L
jump_i <- 0L
jump_j <- 0L
for (i in n:1){ # cols
# all possible combination
next_max <- m * (i-1)
if(max_size!=0 & next_max < max_size & i * m < max_size) {
jump_i <- jump_i + 1
next()
}
comb_col <- combinations(n,i)
for (k in 1:nrow(comb_col)){
col <- as.integer(comb_col[k,])
for(j in m:1){ # rows
if (i*j < max_size ) {
jump_j <- jump_j +1
next()
}
comb_row <- combinations(m,j)
for (l in 1:nrow(comb_row)){
row <- as.integer(comb_row[l,])
y <- x[row, col, drop=F]
if(all(y > 0) & max_size <= length(row)*length(col)){
if(max_size == length(row)*length(col)){
if(sum(y) > max_sum){
max_size <- length(row) * length(col)
max_cols <- col
max_rows <- row
max_sum <- sum(y)}
} else {
max_size <- length(row) * length(col)
max_cols <- col
max_rows <- row
max_sum <- sum(y)
}
}
}
}
}
}
return(x[max_rows,max_cols, drop=F])
}
希望这对你有用,任何问题请给我发电子邮件。
推荐阅读
- sql - 用于查找匹配项的递归 SQL 查询
- python - AWS Lambda:如何读取 S3 存储桶中的 CSV 文件然后将其上传到另一个 S3 存储桶?
- r - Highcharts股票图表X轴日期问题
- python - 将 fastAPI POST 保存到 csv
- javascript - nodemon clean exit - 在重启前等待更改
- c# - 能够在不打开连接的情况下访问数据库,使用 Dapper
- angular - 如何通过单击角度获取行数据表
- xamarin.forms - 无法从视图中检索自定义控件值
- python - 查找元素文本列表的最有效方法 Selenium Python
- sql - 从 SQL Server 中的行连接