[英]Function that subsets a dataframe to the “best square” in R
我的目標是在R中編寫一個將數據框作為輸入並返回其“最佳平方子集”的函數。
最好的平方子集,我的意思是輸出需要確認以下內容:
讓我們以以下三個示例為例:
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。 例如,選擇“星期五”,“星期四”,“下午”,晚上的得分為4
> output2
Afternoon Evening
Friday 1227364 570618
Monday 219402 167216
Thursday 530891 88702
Tuesday 153124 161006
在這里,某人的第一個想法是選擇星期一,星期二和星期三的所有時間,並獲得9分。但是,Wendesday晚間的42分驗證了第一個標准。 星期一和星期二的所有天和時間總分/區域為6
> output3
Afternoon Evening
Friday 20800 21679
在這里,我們有兩個可能的正方形可以驗證前兩個條件:星期五下午和晚上或星期五和星期三下午。 我們必須選擇第一種方法,因為單元格內的總和要高於第二種情況。 此規則僅在平局的情況下適用。
最直觀的解決方案是遍歷行和列的所有可能組合,並檢查選定的行和列是否形成一個完整的正方形,如果是,則檢查是否形成最大的正方形。 這種方法的潛在問題是,如果您有許多列和行,則需要花費一定的時間才能完成,這不是最佳選擇。 當列和行的數量不大於12時,我對這里出現的問題的回答相當有效(在具有16GB RAM,2.7 GHz CPU和Windows 10pro 64位,R版本3.5.1的PC上)
#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])
}
希望這對您有用,如有任何問題,請給我發送電子郵件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.