2

我正在尝试重新排序data.frame包含大约 250,000 行和 7 列的 a。我想要在顶部的行是第data.frame2 列包含最低值和第 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)

如果有人有任何想法,我会全力以赴。谢谢!

4

4 回答 4

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)]to desiredOrder[seq_len(1)]测试特定行的所需订单子集何时等于所需订单的所需子集。(我认为sapplywithwhich和的某种组合all

一旦您确定了与所需结果匹配的所有行,您可以使用它setdiff来查找不匹配的行,然后tt使用此new order向量重新排序。

于 2013-01-11T01:45:23.213 回答
0

一种可能的方法是对列中的值进行加权排名。这将类似于等级回归。7 列 250K 行并不是那么大。对于您希望低值具有更高权重的那些,您可以从 NROW(dfrm) 中减去排名。如果您想在该列排序方案中缩放 wieighting,则只需乘以权重向量:例如 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 的最低值排在第一位,因为您暗示了一个多重标准。如果这与您想象的不完全一样,您仍然可以重新加权。

于 2013-01-11T02:37:50.977 回答
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
于 2013-01-11T06:55:00.280 回答
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
于 2013-01-11T03:05:41.600 回答