R 通过多列排列对数据帧中的行重新排序
我正在尝试对包含大约250000行和7列的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作为最低值的任何行都将被忽略,并在已排序行的下方保持未排序状态。我正在努力为我的问题找到任
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