[英]Permutations from columns of a data frame in R with specific conditions
這可能是一個相當復雜的問題,因此,如果有人至少可以將我指向正確的方向,我可能可以自行解決其余問題。
樣本數據:
dat <- data.frame(A = c(1, 4, 5, 3, NA, 5), B = c(6, 5, NA, 5, 3, 5), C = c(5, 3, 1, 5, 3, 7), D = c(5, NA, 3, 10, 4, 5))
A B C D
1 1 6 5 5
2 4 5 3 NA
3 5 NA 1 3
4 3 5 5 10
5 NA 3 3 4
6 5 5 7 5
我想從上表中找到不同長度的字母序列的所有可能排列。 例如,一個有效的字母序列可能是: ACADDB
。 另一個有效的序列可以是BCC
。
但是,我要注意一些例外情況:
請注意,在上面的示例中,最小序列長度為3,最大序列長度等於行數。 我希望能夠指定最小值(最大值將始終等於行數,在示例數據的情況下為6)。
請注意,如果序列長度小於6,則無法通過跳過行來生成序列長度。 換句話說,任何短序列都必須來自連續的行。 根據注釋進行說明 :短序列不必從第1行開始。短序列可以從第3行開始,並從連續的行一直延續到第6行。
請注意,在第2行的D列中有一個NA
。 這意味着D在第2行中不可用於采樣。因此ABD
是有效的組合,但ADD
無效。
注意每個單元格中都有一個特定的值。 可以通過匯總表中顯示的所選字母的值來對所選的每個序列進行排序。 使用上面的示例, ACADDB
的排名將為1+3+5+10+4+5
。 因此,當生成所有可能的序列時,它們應按從最高到最低的順序排序。
我想將所有這三個規則應用於上面列出的數據表,以找到可能的最小長度3和最大長度6的序列的所有組合。
請讓我知道是否需要澄清!
抱歉,我不再做任何R作業,所以我將嘗試提供骯臟的程式碼...
addPointsToSequence <- function(seq0, currRow){
i<-0;
for(i in 1:4){# 4 is the number of columns
seq2 = seq0
if (!is.na(dat[currRow,i])){
# add the point at the end of seq2
seq2 = cbind(seq2,dat[currRow,i])
# here I add the value, but you may prefer
# adding the colnames(dat)[i] and using the value to estimate the value of this sequence, in another variable
if(length(seq2) >= 3){
# save seq2 as an existing sequence where you need to
print (seq2)
}
if(currRow < 6){# 6 is the number of rows in dat (use nrow?)
addPointsToSequence(seq2, currRow+1)
}
}
}
}
dat <- data.frame(A = c(1, 4, 5, 3, NA, 5), B = c(6, 5, NA, 5, 3, 5), C = c(5, 3, 1, 5, 3, 7), D = c(5, NA, 3, 10, 4, 5))
for (startingRow in 1:4){
#4 is the last row you can start from to make a length3 sequence
emptySequence <- {};
addPointsToSequence(emptySequence , i);
}
原則上,我想使用expand.grid
來執行此操作。 使用您的示例數據,我在這里得出了基礎知識:
dat <- data.frame(A = c(1, 4, 5, 3, NA, 5),
B = c(6, 5, NA, 5, 3, 5),
C = c(5, 3, 1, 5, 3, 7),
D = c(5, NA, 3, 10, 4, 5))
dat[,1][!is.na(dat[,1])] <- paste("A",na.omit(dat[,1]),sep="-")
dat[,2][!is.na(dat[,2])] <- paste("B",na.omit(dat[,2]),sep="-")
dat[,3][!is.na(dat[,3])] <- paste("C",na.omit(dat[,3]),sep="-")
dat[,4][!is.na(dat[,4])] <- paste("D",na.omit(dat[,4]),sep="-")
transp_data <- as.data.frame(t(dat))
data_list <- list(V1 = as.vector(na.omit(transp_data$V1)),
V2 = as.vector(na.omit(transp_data$V2)),
V3 = as.vector(na.omit(transp_data$V3)),
V4 = as.vector(na.omit(transp_data$V4)),
V5 = as.vector(na.omit(transp_data$V5)),
V6 = as.vector(na.omit(transp_data$V6)))
此代碼可讓您從本質上將數據幀轉換為不同長度的向量列表(原始數據中每個變量一個元素,但省略了NA等)。 您要執行此操作的原因是,通過使用expand.grid
函數,可以輕松輕松地找到可接受的組合。
要解決這六個問題,您只需使用:
grid_6 <- do.call(what = expand.grid,
args = data_list)
這將為您提供滿足六個條件的所有可能排列的列表(即沒有NA元素)。 您可以使用一些正則表達式提取數字數據(這不是非常矢量化的方式,但這是一件復雜的事情,我沒有時間將其完全放入函數中)。
grid_6_letters <- grid_6
for(x in 1:ncol(grid_6_letters)) {
for(y in 1:nrow(grid_6_letters)) {
grid_6_letters[y,x] <- gsub(pattern = "-[0-9]*",replacement = "",x = grid_6_letters[y,x])
}
}
grid_6_numbers <- grid_6
for(x in 1:ncol(grid_6_numbers)) {
for(y in 1:nrow(grid_6_numbers)) {
grid_6_numbers[y,x] <- gsub(pattern = "^[ABCD]-",replacement = "",x = grid_6_numbers[y,x])
}
grid_6_numbers[[x]] <- as.numeric(grid_6_numbers[[x]])
}
grid_6_letters$Total <- rowSums(grid_6_numbers)
grid_6_letters <- grid_6_letters[order(grid_6_letters$Total,decreasing = TRUE),]
無論如何,如果您想獲得各種較低級別的組合,可以通過在列表的子集上簡單地使用expand.grid
並使用rbind
組合它們(根據需要明智地使用setNames
)來實現。
grid_3 <- rbind(setNames(do.call(what = expand.grid,args = list(data_list[1:3],stringsAsFactors = FALSE)),nm = c("V1","V2","V3")),
setNames(do.call(what = expand.grid,args = list(data_list[2:4],stringsAsFactors = FALSE)),nm = c("V1","V2","V3")),
setNames(do.call(what = expand.grid,args = list(data_list[3:5],stringsAsFactors = FALSE)),nm = c("V1","V2","V3")),
setNames(do.call(what = expand.grid,args = list(data_list[4:6],stringsAsFactors = FALSE)),nm = c("V1","V2","V3")))
無論如何,經過一些時間和編程,您可以將其包裝到比我的示例更好的函數中,但希望它可以幫助您入門。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.