首页 文章

具有特定条件的R中数据帧的列的排列

提问于
浏览
0

这可能是一个相当复杂的问题,所以如果有人能够至少指出我正确的方向,我可以自己找出其余的 .

样本数据:

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

我想从上面的表中找到所有可能的不同长度的字母序列的排列 . 例如,一个有效的字母序列可能是: A C A D D B . 另一个有效序列可能是 B C C .

但是,我想遵循一些例外情况:

1.必须能够指定返回序列的最小长度 .

请注意,在我上面的示例中,最小序列长度为3,最大序列长度等于行数 . 我希望能够指定最小值(最大值将始终等于行数,在样本数据的情况下为6) .

请注意,如果序列长度小于6,则无法通过跳过行生成它 . 换句话说,任何短序列必须来自连续的行 . Clarification based on comments :短序列不必从第1行开始 . 短序列可以从第3行开始并继续向前通过连续行到第6行 .

2.具有NA值的字母无法进行采样 .

请注意,在第2行中,D列中有 NA . 这意味着D在第2行中不可用于采样 . 因此 A B D 将是有效组合,但 A D D 无效 .

3.必须根据每个单元格中的值对序列进行排序 .

注意每个单元格中的特定值 . 所选择的每个序列可以通过将所选字母的表中所示的值相加来对其进行排序 . 使用上面的示例 A C A D D B 将具有 1+3+5+10+4+5 的等级 . 因此,当生成所有可能的序列时,它们应该从最高等级到最低等级排序 .

我想将所有这三个规则应用于上面列出的数据表,以找到最小长度为3和最大长度为6的所有序列组合 .

如果我需要澄清任何事情,请告诉我!

2 回答

  • 1

    原则上,您希望使用 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")))
    

    无论如何,通过一些时间和编程,你可以把它包装成一个比我的例子好得多的函数,但希望它能让你开始 .

  • 1

    对不起,我不再做任何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);
    }
    

相关问题