【问题标题】:pandas time series multiple slice熊猫时间序列多切片
【发布时间】:2015-06-09 01:52:27
【问题描述】:

从pandas文档中可以看出你可以去:

df.loc[['a','b','c'],:]

时间序列,为什么不去:

x = df.loc[['2005-10-27 14:30':'2005-10-27 15:15', '2006-04-14 14:40':'2006-04-14 15:20', '2008-01-25 14:30':'2008-01-25 15:30'],:]

我收到语法错误。你不能在一个时间序列上做多个切片范围吗?有解决办法吗?

【问题讨论】:

  • 您正在尝试使用字符串而不是时间戳进行索引。您正在尝试使用切片对象列表。
  • 它与时间序列并没有真正的关系。通常,您不能像这样组合切片和列表。主要选项是像下面的 Mark 那样手动构建一个列表。另请参阅:stackoverflow.com/questions/29241836/…

标签: python indexing pandas time-series slice


【解决方案1】:

这个question 提到了 numpy.r_ 但我不知道如何让它与切片列表一起工作,所以我使用了 hstack 和 arange

import numpy as np
import pandas as pd

def loop_version(df, desired):
    # let's loop through the desired ranges and compile our selection           
    x = pd.DataFrame()
    for (start, stop) in desired:
        selection = df[(df.index >= pd.Timestamp(start)) & 
            (df.index <= pd.Timestamp(stop))]
        x = x.append(selection)

    # and let's have a look at what we found ...
    return x

def vectorized_version(df, desired):
    # first flatten the list
    times = np.array(desired).flatten()
    # use searchsorted to find the indices of the 
    # desired times in df's index
    ndxlist = df.index.searchsorted(np.array(times))
    # use np.arange to convert pairs of values in ndxlist to a 
    # range of indices, similar to np.r_
    ndxlist = np.hstack([np.arange(i1, i2) for i1, i2 in 
                        zip(ndxlist[::2], ndxlist[1::2])])
    return df.iloc[ndxlist]

In [2]: # let's create some fake data
In [3]: date_range = pd.date_range('2005-01-01', '2008-12-31', freq='9min')
In [4]: l = len(date_range)
In [5]: df = pd.DataFrame({'normal': np.random.randn(l), 'uniform':np.random.rand(l), 
   ...:     'datetime':date_range, 'integer':range(l)}, index=date_range)
In [6]: # let's identify the periods we want
   ...: desired = [('2005-10-27 14:30','2005-10-27 15:15'), 
   ...:            ('2006-04-14 14:40','2006-04-14 15:20'), 
   ...:            ('2008-01-25 14:30','2008-01-25 15:30')]

In [7]: loop_version(df, desired).equals(vectorized_version(df, desired))
Out[7]: True

In [8]: % timeit loop_version(df, desired)
5.53 ms ± 225 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [9]: % timeit vectorized_version(df, desired)
308 µs ± 1.26 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

  • 同意,对于大型数据帧,如果时间没有重叠,这将大大提高效率。
【解决方案2】:

虽然 DataFrame 索引将接受列索引列表,但它不会接受行切片对象列表。

这应该做你想做的事,它会遍历你想要的范围,编译一个新的 DataFrame。

import numpy as np
import pandas as pd

# let's create some fake data
date_range = pd.date_range('2005-01-01', '2008-12-31', freq='9min')
l = len(date_range)
df = pd.DataFrame({'normal': np.random.randn(l), 'uniform':np.random.rand(l), 
    'datetime':date_range, 'integer':range(l)}, index=date_range)

# let's identify the periods we want
desired = [('2005-10-27 14:30','2005-10-27 15:15'), 
           ('2006-04-14 14:40','2006-04-14 15:20'), 
           ('2008-01-25 14:30','2008-01-25 15:30')]

# let's loop through the desired ranges and compile our selection           
x = pd.DataFrame()
for (start, stop) in desired:
    selection = df[(df.index >= pd.Timestamp(start)) & 
        (df.index <= pd.Timestamp(stop))]
    x = x.append(selection)

# and let's have a look at what we found ...
print(x)

【讨论】:

  • 很好的答案,尽管为了提高效率(在重要的情况下),您可能更愿意仅在索引上而不是在整个数据帧上执行此操作。
  • 没有更有效的方法可以做到这一点,即避免循环吗?如果所需的间隔不重叠,则可以使用 np.searchsorted 避免循环,但如果间隔重叠则中断......
  • @feilchenfeldt this 文章,尤其是在 IndexSlices 上的文章可能适合您的用例。
  • 为什么要进行比较? Pandas 支持使用日期字符串进行切片。 selection = df[slice(start, stop)] 应该可以工作。或x = pd.concat([df[slice(*date_range)] for date_range in desired])
猜你喜欢
  • 2018-08-10
  • 2020-03-17
  • 2019-02-03
  • 2020-02-18
  • 1970-01-01
  • 2018-07-12
  • 2017-02-22
  • 2014-10-08
  • 2020-08-20
相关资源
最近更新 更多