R 通过多列排列对数据帧中的行重新排序

R 通过多列排列对数据帧中的行重新排序,r,R,我正在尝试对包含大约250000行和7列的data.frame进行重新排序。我希望位于data.frame顶部的行是第2列包含最低值,第7列包含最高值,但按从低到高的顺序排列的列:2,5,1,4,6,3,7(因此第5列包含第二个最低值等) 一旦识别出与此序列匹配的任何行,它将继续查找列值在序列2、5、1、4、6和2、5、1、4中从最低到最高的行,依此类推,直到只对列2最低的行和其他列值进行随机分类。没有列2作为最低值的任何行都将被忽略,并在已排序行的下方保持未排序状态。我正在努力为我的问题找到任

我正在尝试对包含大约250000行和7列的
data.frame
进行重新排序。我希望位于
data.frame
顶部的行是第2列包含最低值,第7列包含最高值,但按从低到高的顺序排列的列:2,5,1,4,6,3,7(因此第5列包含第二个最低值等)

一旦识别出与此序列匹配的任何行,它将继续查找列值在序列2、5、1、4、6和2、5、1、4中从最低到最高的行,依此类推,直到只对列2最低的行和其他列值进行随机分类。没有列2作为最低值的任何行都将被忽略,并在已排序行的下方保持未排序状态。我正在努力为我的问题找到任何可行的解决方案——就提供与我正在处理的数据类似的数据而言,我能做的最好的事情是:

df<-data.frame(matrix(rnorm(70000), nrow=10000))
df<-abs(df)

df鉴于您有一个统一类型(数字)的较大数据集,我建议使用矩阵而不是data.frame

 tt <- abs(matrix(rnorm(70000), nrow=10000))

tt一种可能的方法是对列中的值进行权重排序。这有点像等级回归。7列250K行并没有那么大。对于希望低值具有更高权重的值,可以从NROW(dfrm)中减去秩。如果您想在该列排序方案中缩放权重,那么jsut乘以权重向量:比如c(1、.6、.3、0、.3、.6、1)

dmat像这样:

dat <- as.matrix(df)
rnk <- t(apply(dat, 1, rank))
desiredRank <- order(c(2,5,1,4,6,3,7))
rnk.match <- rnk == matrix(desiredRank, nrow(rnk), ncol(rnk), byrow = TRUE)
match.score <- apply(rnk.match, 1, match, x = FALSE) - 1
match.score[is.na(match.score)] <- ncol(dat)
out <- dat[order(match.score, decreasing = TRUE), ]

head(out)
#            X1         X2        X3        X4        X5       X6        X7
#[1,] 0.7740246 0.19692680 1.5665696 0.9623104 0.2882492 1.367786 1.8644204
#[2,] 0.5895921 0.00498982 1.7143083 1.2698382 0.1776051 2.494149 1.4216615
#[3,] 0.1981111 0.11379934 1.0379619 0.2130251 0.1660568 1.227547 0.9248101
#[4,] 0.7507257 0.23353923 1.6502192 1.2232615 0.7497352 2.032547 1.4409475
#[5,] 0.5418513 0.06987903 1.8882399 0.6923557 0.3681018 2.172043 1.2215323
#[6,] 0.1731943 0.01088604 0.6878847 0.2450998 0.0125614 1.197478 0.3087192

您可以使用以下事实:
order()
索引返回给排序,
这正是你想要匹配的

For example if we apply `order` twice to each row of 
  [1,]   23   17  118   57   20   66  137
  [2,]   56   42   52   66   47    8   29
  [3,]   35    5   76   35   29  217   89

We would get
  [1,]    2    5    1    4    6    3    7
  [2,]    6    7    2    5    3    1    4
  [3,]    2    5    1    4    3    7    6
然后,您只需检查哪些行与您要查找的匹配



有几种方法可以实现这一点,下面是一个示例,我们在其中创建
一种逻辑矩阵,
比较
,指示行中的每个元素是否 处于“正确”位置,如
expectedOrder
所示

然后,我们根据“正确列”中的元素数量对原始行进行排序。(当然,不严格地使用这个短语)

#假设mydf是您的数据帧或矩阵
#列的预期顺序

你的问题描述很难理解。也许您可以创建一个小示例(6 x 4?),其中显示了过程的起点,然后是所需的结果?您并没有完全回答这个问题,因为您的排序只包括至少与前四行匹配的行。还要注意以编程方式使用负索引。如果
topRows
为空,则
rbind(mydf[topRows,],mydf[-topRows,])
也将为空。谢谢您的回答。然而,当涉及到使用sapply时,我遇到了问题,sapply和所有函数都是如此。看起来行是按我所希望的方式排序的,但在某些情况下,它似乎是按列顺序排序,而不是按所需的列顺序排序。很明显,我做错了一些我无法理解的事情,你能给我一个更进一步的想法,当你建议这些函数时,你在想什么吗?非常感谢
dmat <- matrix(sample(20, 20*7, repl=TRUE), 20, 7)
dfrm <- as.data.frame(dmat)

dfrm$wt <- sapply( dfrm[ c(2,5,1,4,6,3,7)] , rank); dfrm
 dfrm$wt[,1:3]  <- rep(NROW(dfrm),3) - dfrm$wt[ , 1:3] 
 dfrm$wt <- dfrm$wt*rep(c(1, .6, .3,  0, .3, .6, 1), each=NROW(dfrm))
 dfrm[ order( apply( dfrm$wt, 1, FUN=sum), decreasing=TRUE ) , ]
dat <- as.matrix(df)
rnk <- t(apply(dat, 1, rank))
desiredRank <- order(c(2,5,1,4,6,3,7))
rnk.match <- rnk == matrix(desiredRank, nrow(rnk), ncol(rnk), byrow = TRUE)
match.score <- apply(rnk.match, 1, match, x = FALSE) - 1
match.score[is.na(match.score)] <- ncol(dat)
out <- dat[order(match.score, decreasing = TRUE), ]

head(out)
#            X1         X2        X3        X4        X5       X6        X7
#[1,] 0.7740246 0.19692680 1.5665696 0.9623104 0.2882492 1.367786 1.8644204
#[2,] 0.5895921 0.00498982 1.7143083 1.2698382 0.1776051 2.494149 1.4216615
#[3,] 0.1981111 0.11379934 1.0379619 0.2130251 0.1660568 1.227547 0.9248101
#[4,] 0.7507257 0.23353923 1.6502192 1.2232615 0.7497352 2.032547 1.4409475
#[5,] 0.5418513 0.06987903 1.8882399 0.6923557 0.3681018 2.172043 1.2215323
#[6,] 0.1731943 0.01088604 0.6878847 0.2450998 0.0125614 1.197478 0.3087192
head(match.score[order(match.score, decreasing = TRUE)])
# [1] 7 5 5 5 5 5
For example if we apply `order` twice to each row of 
  [1,]   23   17  118   57   20   66  137
  [2,]   56   42   52   66   47    8   29
  [3,]   35    5   76   35   29  217   89

We would get
  [1,]    2    5    1    4    6    3    7
  [2,]    6    7    2    5    3    1    4
  [3,]    2    5    1    4    3    7    6
# assuming mydf is your data frame or matrix

# the expected order of the columns
expectedOrder <- c(2,5,1,4,6,3,7)

# apply the order function twice. 
ordering <- apply(mydf, 1, function(r) order(r) )  

# Recall that the output of apply is transposed relative to the input. 
# We make use of this along with the recycling of vectors for the comparison
comparisons <-  ordering == expectedOrder

# find all rows with at least matches to 2,5,1,4
topRows  <- which(colSums(comparisons[1:4, ])==4)

# reorder the indecies based on the total number of matches in comparisons
#  ie:  first all 7-matches, then 5-matches, then 4-matches
topRows <- topRows[order(colSums(comparisons[,topRows]), decreasing=TRUE)]

# reorder the dataframe (or matrix) 
mydf.ordered <- 
  rbind(mydf[topRows, ],  
        mydf[-topRows,])

head(mydf.ordered)
 #    X1 X2  X3  X4  X5  X6  X7
 #    23 17 118  57  20  66 137
 #    39 21 102  50  24  53 163
 #    80  6 159 116  44 139 248
 #   131  5 185 132 128 147 202
 #    35 18  75  40  33  67 151
 #    61 14 157  82  57 105 355