Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何按多列对数据帧进行排序_R_Sorting_Dataframe_R Faq - Fatal编程技术网

R 如何按多列对数据帧进行排序

R 如何按多列对数据帧进行排序,r,sorting,dataframe,r-faq,R,Sorting,Dataframe,R Faq,我想按多列对data.frame进行排序。例如,对于下面的data.frame,我希望按列z(降序)排序,然后按列b(升序)排序: ddWith,发布在R wiki的提示部分,这很容易实现 sort(dd,by = ~ -z + b) # b x y z # 4 Low C 9 2 # 2 Med D 3 1 # 1 Hi A 8 1 # 3 Hi A 9 1 您可以直接使用该函数,而无需借助附加工具——请参阅下面这个简单的答案,它使用了示例(顺序)代码顶部的技巧: R> d

我想按多列对data.frame进行排序。例如,对于下面的data.frame,我希望按列
z
(降序)排序,然后按列
b
(升序)排序:

ddWith,发布在R wiki的提示部分,这很容易实现

sort(dd,by = ~ -z + b)
#     b x y z
# 4 Low C 9 2
# 2 Med D 3 1
# 1  Hi A 8 1
# 3  Hi A 9 1
您可以直接使用该函数,而无需借助附加工具——请参阅下面这个简单的答案,它使用了
示例(顺序)
代码顶部的技巧:

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
大约2年多后编辑:只是被问到如何按列索引进行编辑。答案是只需将所需的排序列传递给
order()
函数:

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

而不是使用列的名称(和
with()
以便更容易/更直接地访问)。

或者,使用包推断器

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))
库(演绎器)

dd或者您可以使用软件包doBy

library(doBy)
dd <- orderBy(~-z+b, data=dd)
库(doBy)

dd如果SQL对您来说是自然产生的,
sqldf
包按照Codd的意图处理
ORDER BY

假设您有一个
data.frame
a
并希望使用名为
x
的列对其进行降序排序。调用排序后的
data.frame
newdata

newdata <- A[order(-A$x),]

其中
x
z
data.frame
A
中的一些列。这意味着排序
data.frame
A
方法是
x
降序、
y
升序和
z
降序。

Dirk的答案很好,但如果需要继续排序,则需要将排序重新应用到该数据帧的名称上。使用示例代码:

dd <- dd[with(dd, order(-z, b)), ] 
dd您的选择
  • 订单
    from
    base
  • 排列
    来自
    dplyr
  • setorder
    setorderv
    来自
    数据表
  • 排列
    plyr
  • sort
    from
    taRifx
  • orderBy
    from
    doBy
  • sortData
    from
    explorer
大多数情况下,您应该使用
dplyr
data.table
解决方案,除非没有依赖关系很重要,在这种情况下,请使用
base::order


我最近将sort.data.frame添加到CRAN包中,使其与类兼容,如下所述:

因此,给定data.frame dd,可以按如下方式排序:

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )

基准测试:注意,我在一个新的R会话中加载了每个包,因为有很多冲突。尤其是加载doBy包会导致
sort
返回“以下对象从'x(位置17)'屏蔽:b,x,y,z”,加载推断器包会覆盖Kevin Wright或taRifx包的
sort.data.frame

#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(microbenchmark)

# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
    dd[order(-dd$z, dd$b),],
    times=1000
)
中位时间:1567

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)
中位时间:862

library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)
中位时间:1694

请注意,doBy加载包需要很长一段时间

library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)
无法使演绎器加载。需要JGR控制台

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}

microbenchmark(esort(dd, -z, b),times=1000)

德克的答案很好。它还强调了用于索引
data.frame
s和
data.table
s的语法的一个关键区别:

## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]
这两个调用之间的差异很小,但可能会产生重要的后果。特别是如果您编写生产代码和/或关心研究的正确性,最好避免不必要的重复变量名<代码>数据表
帮助你做到这一点

下面是一个重复变量名可能会给您带来麻烦的示例:

让我们从Dirk的答案中改变上下文,假设这是一个更大项目的一部分,其中有很多对象名称,它们很长且有意义;它被称为
quarteryReport
,而不是
dd
。它变成:

quarterlyreport[with(quarterlyreport,order(-z,b)),]
好的。这没什么错。接下来,你的老板要求你在报告中包括上一季度的报告。你仔细检查你的代码,在不同的地方添加一个对象
lastquarterlyreport
,不知怎的(到底是怎么回事?)

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
这不是你的意思,但你没有发现它,因为你做得很快,而且它位于类似代码的页面上。代码不会崩溃(没有警告也没有错误),因为R认为这就是你的意思。你希望读你的报告的人能发现,但也许他们不会。如果您经常使用编程语言,那么这种情况可能大家都很熟悉。你会说这是一个“打字错误”。我会纠正你对老板说的“拼写错误”

实际上,我们关心的是像这样的小细节。因此,我们做了一些简单的工作,以避免重复键入变量名。非常简单的事情<代码>i
已在
dd
的框架内自动计算。您根本不需要使用()进行

而不是

dd[with(dd, order(-z, b)), ]
只是

dd[order(-z, b)]
quarterlyreport[order(-z,b)]
而不是

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
只是

dd[order(-z, b)]
quarterlyreport[order(-z,b)]

虽然差别很小,但总有一天可能会保住你的脖子。在权衡这个问题的不同答案时,考虑把变量名称的重复作为决定的标准之一。有些答案有很多重复,有些则没有。

我通过下面的例子了解了
顺序
,这让我困惑了很长一段时间:

set.seed(1234)

ID        = 1:10
Age       = round(rnorm(10, 50, 1))
diag      = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)

data = data.frame(ID, Age, Diagnosis)

databyAge = data[order(Age),]
databyAge
此示例有效的唯一原因是
顺序
是按
向量年龄
排序,而不是按
数据框数据
中名为
年龄
的列排序

databyage = my.data[order(my.data$age),]
要了解这一点,请使用
read.table
创建一个相同的数据框,列名称略有不同,但不使用上述任何向量:

my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)
以下行之所以有效,是因为
order
my.data
中的
age
列进行排序

databyage = my.data[order(my.data$age),]
我认为这是值得张贴鉴于我是多么困惑这个例子这么长时间。如果这篇文章不适合这个线程,我可以删除它

编辑:
my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)
databyage = my.data[order(age),]
databyage = my.data[order(my.data$age),]
set.seed(1234)

v1  <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2  <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3  <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4  <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)

df.1 <- data.frame(v1, v2, v3, v4) 
df.1

rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1

order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1

order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2

rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1) 
rdf.3

order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3
library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)
arrange(dd, desc(z),  b)

    b x y z
1 Low C 9 2
2 Med D 3 1
3  Hi A 8 1
4  Hi A 9 1
 dd <- dd[order(dd$b, decreasing = FALSE),]
dd <- dd[order(dd$z, decreasing = TRUE),]
require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)

set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
                 x = sample(c("A", "D", "C"), 1e8, TRUE),
                 y = sample(100, 1e8, TRUE),
                 z = sample(5, 1e8, TRUE), 
                 stringsAsFactors = FALSE)
orderBy( ~ -z + b, data = dat)     ## doBy
plyr::arrange(dat, desc(z), b)     ## plyr
arrange(dat, desc(z), b)           ## dplyr
sort(dat, f = ~ -z + b)            ## taRifx
dat[with(dat, order(-z, b)), ]     ## base R

# convert to data.table, by reference
setDT(dat)

dat[order(-z, b)]                  ## data.table, base R like syntax
setorder(dat, -z, b)               ## data.table, using setorder()
                                   ## setorder() now also works with data.frames 

# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package      function    Time (s)  Peak memory   Memory used
# ------------------------------------------------------------
# doBy          orderBy      409.7        6.7 GB        4.7 GB
# taRifx           sort      400.8        6.7 GB        4.7 GB
# plyr          arrange      318.8        5.6 GB        3.6 GB 
# base R          order      299.0        5.6 GB        3.6 GB
# dplyr         arrange       62.7        4.2 GB        2.2 GB
# ------------------------------------------------------------
# data.table      order        6.2        4.2 GB        2.2 GB
# data.table   setorder        4.5        2.4 GB        0.4 GB
# ------------------------------------------------------------
DF <- DF[order(...)]
library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872
library(dplyr)
library(data.table)
df1 <- tbl_df(iris)
#using strings or formula
arrange_(df1, c('Petal.Length', 'Petal.Width'))
arrange_(df1, ~Petal.Length, ~Petal.Width)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.4         3.9          1.3         0.4  setosa
7           5.5         3.5          1.3         0.2  setosa
8           4.4         3.0          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...


#Or using a variable
sortBy <- c('Petal.Length', 'Petal.Width')
arrange_(df1, .dots = sortBy)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.5         3.5          1.3         0.2  setosa
7           4.4         3.0          1.3         0.2  setosa
8           4.4         3.2          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...

#Doing the same operation except sorting Petal.Length in descending order
sortByDesc <- c('desc(Petal.Length)', 'Petal.Width')
arrange_(df1, .dots = sortByDesc)
dt1 <- data.table(iris) #not really required, as you can work directly on your data.frame
sortBy <- c('Petal.Length', 'Petal.Width')
sortType <- c(-1, 1)
setorderv(dt1, sortBy, sortType)
dt1
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
  1:          7.7         2.6          6.9         2.3 virginica
  2:          7.7         2.8          6.7         2.0 virginica
  3:          7.7         3.8          6.7         2.2 virginica
  4:          7.6         3.0          6.6         2.1 virginica
  5:          7.9         3.8          6.4         2.0 virginica
 ---                                                            
146:          5.4         3.9          1.3         0.4    setosa
147:          5.8         4.0          1.2         0.2    setosa
148:          5.0         3.2          1.2         0.2    setosa
149:          4.3         3.0          1.1         0.1    setosa
150:          4.6         3.6          1.0         0.2    setosa
> library(rgr)
> gx.sort.df(dd, ~ -z+b)
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
dfOrder(myDf, columnIndices)
dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))
ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]

##        Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
##    14           4.3         3.0          1.1         0.1     setosa
##    9            4.4         2.9          1.4         0.2     setosa
##    39           4.4         3.0          1.3         0.2     setosa
##    43           4.4         3.2          1.3         0.2     setosa
##    42           4.5         2.3          1.3         0.3     setosa
##    4            4.6         3.1          1.5         0.2     setosa
##    48           4.6         3.2          1.4         0.2     setosa
##    7            4.6         3.4          1.4         0.3     setosa
##    (...)