【问题标题】:How to reverse the order of a dataframe in R如何在R中反转数据框的顺序
【发布时间】:2016-10-11 10:30:41
【问题描述】:

我没完没了地寻找这个,但不知何故没有解决这个简单问题。

我有一个名为“价格”的数据框,其中有 4 列,其中一列是历史日期列表,另外三列是产品价格列表。

1   10/10/2016  53.14   50.366  51.87
2   07/10/2016  51.93   49.207  50.38
3   06/10/2016  52.51   49.655  50.98
4   05/10/2016  51.86   49.076  50.38
5   04/10/2016  50.87   48.186  49.3
6   03/10/2016  50.89   48.075  49.4
7   30/09/2016  50.19   47.384  48.82
8   29/09/2016  49.81   46.924  48.4
9   28/09/2016  49.24   46.062  47.65
10  27/09/2016  46.52   43.599  45.24

列表有 252 个价格。如何将我的输出与列表底部的最新日期一起存储,并在列表底部以最新价格列出相应的价格?

【问题讨论】:

  • 如果df 是您的data.frame,则日期列称为date,并且您想按日期对数据集进行排序,只需尝试df[order(df$date),]
  • 还要确保您的date 列设置为as.Date
  • OP 的日期不是Date 对象,不幸的是@Sotos。如果是的话,它将是一个 ISO 格式字符串。不过,我很好奇为什么显示顺序很重要(因为我们可以帮助他们进行依赖顺序的任何处理)。但是,由于 OP 似乎已经以相反的顺序拥有它并且知道行数 df[252:1,] 也可以工作。
  • 使用 TTR 包中的 Bbands 计算布林带是原因。似乎该函数是自下而上计算的 - 如果我错了,请纠正我?
  • 如果问题在于日期列是字符串格式,您可以使用@nicola 的解决方案进行调整:df[order(as.Date(df$date, format = "%m/%d/%Y")),]

标签: r sorting dataframe


【解决方案1】:

另一个tidyverse 解决方案,我认为最简单的是:

df %>% map_df(rev)

或者只使用purrr::map_df,我们可以使用map_df(df, rev)

【讨论】:

  • 应该是 IMO 选择的答案。
  • 同意...如果可以的话,我会放弃更多的选票
  • 此答案会为矩阵列生成错误(诚然,这有点奇怪)。例如:tibble(a=1:2, b=matrix(1:6, nrow = 2)) %>% map_df(rev) # error.
【解决方案2】:

如果您只想反转数据框中的行顺序,可以执行以下操作:

df<- df[seq(dim(df)[1],1),]

【讨论】:

  • 不错的解决方案。但是这里不需要seq。它只会减慢您的代码速度。
【解决方案3】:

只是为了完整起见。这里实际上不需要调用seq。你可以只使用:-R-logic:

### Create some sample data
n=252
sampledata<-data.frame(a=sample(letters,n,replace=TRUE),b=rnorm(n,1,0.7),
                       c=rnorm(n,1,0.6),d=runif(n))

### Compare some different ways to reorder the dataframe
myfun1<-function(df=sampledata){df<-df[seq(nrow(df),1),]}
myfun2<-function(df=sampledata){df<-df[seq(dim(df)[1],1),]}
myfun3<-function(df=sampledata){df<-df[dim(df)[1]:1,]}
myfun4<-function(df=sampledata){df<-df[nrow(df):1,]}

### Microbenchmark the functions


microbenchmark::microbenchmark(myfun1(),myfun2(),myfun3(),myfun4(),times=1000L)
    Unit: microseconds
         expr    min     lq      mean  median      uq      max neval
     myfun1() 63.994 67.686 117.61797 71.3780 87.3765 5818.494  1000
     myfun2() 63.173 67.686  99.29120 70.9680 87.7865 2299.258  1000
     myfun3() 56.610 60.302  92.18913 62.7635 76.9155 3241.522  1000
     myfun4() 56.610 60.302  99.52666 63.1740 77.5310 4440.582  1000

在我的试用中,最快的方法是使用df&lt;-df[dim(df)[1]:1,]。但是使用nrow 而不是dim 只会稍微慢一点。使这成为个人喜好的问题。

在这里使用seq 肯定会减慢进程。

2018 年 9 月更新:

从速度的角度来看,这里几乎没有理由使用dplyr。对于大约 90% 的用户来说,基本的 R 功能就足够了。另外 10% 需要使用dplyr 查询数据库或需要将代码翻译成另一种语言。

## hmhensen's function
dplyr_fun<-function(df=sampledata){df %>% arrange(rev(rownames(.)))}

microbenchmark::microbenchmark(myfun3(),myfun4(),dplyr_fun(),times=1000L)
Unit: microseconds
        expr    min      lq      mean  median      uq    max neval
    myfun3()   55.8   69.75  132.8178  103.85  139.95 8949.3  1000
    myfun4()   55.9   68.40  115.6418  100.05  135.00 2409.1  1000
 dplyr_fun() 1364.8 1541.15 2173.0717 1786.10 2757.80 8434.8  1000

【讨论】:

  • 您的dplyr 解决方案将无法按预期工作,因为您按character 类型的行名排序。所以,升序,你会得到:“1”、“10”、“100”、“2”等......
  • @JamesHirschorn 不是我的解决方案。这是 hmhensen 的 dplyr 解决方案。不过我赞成你的评论
  • 所有这些解决方案都因数据帧为零行而中断
【解决方案4】:

另一个tidyverse 解决方案是:

df %>% arrange(desc(row_number()))

【讨论】:

  • 这一点不容忽视,因为它很简单!
  • 请注意,此答案适用于矩阵值列。例如:tibble(a=1:2, b=matrix(1:6, nrow = 2)) %&gt;% arrange(desc(row_number())).
【解决方案5】:

另一种选择是按要排序的向量对列表进行排序,

> data[order(data$Date), ]
# A tibble: 10 x 4
   Date                priceA priceB priceC
   <dttm>               <dbl>  <dbl>  <dbl>
 1 2016-09-27 00:00:00   46.5   43.6   45.2
 2 2016-09-28 00:00:00   49.2   46.1   47.6
 3 2016-09-29 00:00:00   49.8   46.9   48.4
 4 2016-09-30 00:00:00   50.2   47.4   48.8
 5 2016-10-03 00:00:00   50.9   48.1   49.4
 6 2016-10-04 00:00:00   50.9   48.2   49.3
 7 2016-10-05 00:00:00   51.9   49.1   50.4
 8 2016-10-06 00:00:00   52.5   49.7   51.0
 9 2016-10-07 00:00:00   51.9   49.2   50.4
10 2016-10-10 00:00:00   53.1   50.4   51.9

那么如果你这么倾向,你想颠倒顺序,颠倒它,

> data[rev(order(data$Date)), ]
# A tibble: 10 x 4
   Date                priceA priceB priceC
   <dttm>               <dbl>  <dbl>  <dbl>
 1 2016-10-10 00:00:00   53.1   50.4   51.9
 2 2016-10-07 00:00:00   51.9   49.2   50.4
 3 2016-10-06 00:00:00   52.5   49.7   51.0
 4 2016-10-05 00:00:00   51.9   49.1   50.4
 5 2016-10-04 00:00:00   50.9   48.2   49.3
 6 2016-10-03 00:00:00   50.9   48.1   49.4
 7 2016-09-30 00:00:00   50.2   47.4   48.8
 8 2016-09-29 00:00:00   49.8   46.9   48.4
 9 2016-09-28 00:00:00   49.2   46.1   47.6
10 2016-09-27 00:00:00   46.5   43.6   45.2

【讨论】:

    【解决方案6】:

    如果您想在基础 R 中执行此操作:

    df <- df[rev(seq_len(nrow(df))), , drop = FALSE]
    

    此处发布的所有其他基本 R 解决方案在零行数据帧 (seq(0,1) == c(0, 1),这就是我们使用 seq_len) 或单列数据帧 (data.frame(a=7:9)[3:1,] == 9:7,这就是我们使用 @ 的原因) 的边缘情况下都会出现问题987654325@)。

    【讨论】:

      【解决方案7】:

      如果你想坚持使用base R,你也可以使用lapply()

      do.call(cbind, lapply(df, rev))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-15
        • 2012-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-16
        • 1970-01-01
        相关资源
        最近更新 更多