我正在尝试重新排序包含大约250,000行和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)
如果有人有任何想法,我会全力以赴。 谢谢!
答案 0 :(得分:2)
鉴于您有一个统一类型(数字)的大数据集,我建议使用矩阵而不是data.frame
tt <- abs(matrix(rnorm(70000), nrow=10000))
您希望与
匹配的订单 desiredOrder <- c(2,5,1,4,6,3,7)
您需要查找每个行的顺序。我认为这里最容易确保给你一个列表,每行都有一个元素。我建议这样的事情。
orders <- lapply(apply(tt, 1, function(x) list(order(x))), unlist)
然后,您需要经历(从desiredOrder[seq_len(7)]
到desiredOrder[seq_len(1)]
以测试特定行的所需订单子集何时等于所需订单的所需子集。(我在考虑一些sapply
与which
和all
)
找到符合所需结果的所有行后,您可以使用setdiff
查找不匹配的行,然后使用此tt
向量重新排序new order
。
答案 1 :(得分:0)
一种可能的方法是对列中的值进行加权排名。这将是排名回归。 7列250K行不是那么大。对于那些你希望低值具有更高权重的人,你可以从NROW(dfrm)中减去等级。如果你想在该列排序方案中扩展wieighting,那么jsut乘以一个加权向量:比如c(1,.6,.3,0,.3,.6,1)
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 ) , ]
这并不会强制V2的最低值成为第一个,因为您隐含了多个标准。如果这不是你想象的那样,你仍然有能力重新加权。
答案 2 :(得分:0)
像这样:
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
答案 3 :(得分:0)
您可以使用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
然后,您只需要检查哪些行符合您要查找的内容。
comparisons
,表示行的每个元素是否为
处于“正确”位置,如expectedOrder
所示。
# 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