基于列标准的熊猫数据框重采样

Posted

技术标签:

【中文标题】基于列标准的熊猫数据框重采样【英文标题】:Panda Dataframe Resampling based on column criteria 【发布时间】:2017-05-28 00:07:19 【问题描述】:

如果另一列中的单元格符合我的条件,我想重新采样数据框

df = pd.DataFrame(
        'timestamp': [
            '2013-03-01 08:01:00', '2013-03-01 08:02:00',
            '2013-03-01 08:03:00', '2013-03-01 08:04:00',
            '2013-03-01 08:05:00', '2013-03-01 08:06:00'
        ],
        'Kind': [
            'A', 'B', 'A', 'B', 'A', 'B'
        ],
        'Values': [1, 1.5, 2, 3, 5, 3]
    )

对于每个时间戳,我可能有 2-10 种,我想正确地重新采样而不产生NaN。目前我使用下面的代码对整个数据帧重新采样并得到NaNs。我认为这是因为我对某些时间戳有多个条目。

df.set_index('timestamp').resample('5Min').mean()

一种方法是为每种类型创建不同的数据帧,重新采样每个数据帧,然后加入生成的数据帧。我想知道是否有任何简单的方法。

【问题讨论】:

df.groupby('Kind').apply(lambda x: x.set_index('timestamp').resample('5Min').mean()).reset_index()? @Abdou 此代码出错。 @ShankarPandala 什么样的错误?我刚刚使用了提供的示例数据框。您要确保您的 timestamp 属于 datetime 对象。 @Abdou 这是一个语法错误,指出“标识符中的字符无效”。错误指向 x.set_index 它来自于您复制和粘贴代码的方式。相反,编写代码本身。包含代码的多行 cmets 很难复制和粘贴。 【参考方案1】:

设置时间戳以键入日期时间,然后用作索引。

df.timestamp = pd.to_datetime(df.timestamp)
df = df.set_index(["timestamp"])

从您自己选择的列中抽取样本,例如:A 类样本:

df[df.Kind=='A'].sample(1)

 Kind  Values
timestamp                       
2013-03-01 08:03:00    A     2.0

样本然后进行计算:

df[df.Kind=='A'].sample(2).mean()
Values    1.5
dtype: float64

【讨论】:

【参考方案2】:

按照您的说明定义数据框后,您应该首先将timestamp 列转换为datetime。然后将其设置为索引,最后重新采样并找到平均值如下:

import pandas as pd
df = pd.DataFrame(
        'timestamp': [
            '2013-03-01 08:01:00', '2013-03-01 08:02:00',
            '2013-03-01 08:03:00', '2013-03-01 08:04:00',
            '2013-03-01 08:05:00', '2013-03-01 08:06:00'
        ],
        'Kind': [
            'A', 'B', 'A', 'B', 'A', 'B'
        ],
        'Values': [1, 1.5, 2, 3, 5, 3]
    )

df.timestamp = pd.to_datetime(df.timestamp)
df = df.set_index(["timestamp"])
df = df.resample("5Min")    
print df.mean()

这将打印您期望的平均值:

>>> 
Values    2.75

你的数据框会导致:

>>> df
                     Values
timestamp                  
2013-03-01 08:05:00     2.5
2013-03-01 08:10:00     3.0

按种类分组

如果您想按种类分组并获得每种种类的平均值(表示 A 和 B),您可以执行以下操作:

df.timestamp = pd.to_datetime(df.timestamp)
df = df.set_index(["timestamp"])
gb = df.groupby(["Kind"])
df = gb.resample("5Min")
print df.xs("A", level = "Kind").mean()
print df.xs("B", level = "Kind").mean()

结果你会得到:

>>> 
Values    2.666667
Values    2.625

您的数据框最终将如下所示:

>>> df
                            Values
Kind timestamp                    
A    2013-03-01 08:05:00  2.666667
B    2013-03-01 08:05:00  2.250000
     2013-03-01 08:10:00  3.000000

【讨论】:

【参考方案3】:

首先,最好将'timestamp' 列显式转换为DatetimeIndex 类型:

df = pd.DataFrame(
    'timestamp': pd.to_datetime([
        '2013-03-01 08:01:00', '2013-03-01 08:02:00',
        '2013-03-01 08:03:00', '2013-03-01 08:04:00',
        '2013-03-01 08:05:00', '2013-03-01 08:06:00']),
    'Kind':   ['A', 'B', 'A', 'B', 'A', 'B'],
    'Values': [ 1,  4.5,  2,   7,   5,   9] )

请注意B kind 值的变化。现在,当您重新采样mean() 时,将新值估计为两个现有值的平均值。可能会出现多个新数据点位于现有数据点之间,pandasNaNs 填充它们的值。您可以使用ffill()bfill(),具体取决于您希望关闭的时间间隔的一侧。默认情况下它是离开的,所以bfill() 是选择。

 df.set_index('timestamp').groupby('Kind').resample('1.5Min')['Values'].bfill().reset_index()

Out[1]:

    Kind    timestamp       Values
0   A   2013-03-01 08:00:00 1.0
1   A   2013-03-01 08:01:30 2.0
2   A   2013-03-01 08:03:00 2.0
3   A   2013-03-01 08:04:30 5.0
4   B   2013-03-01 08:01:30 4.5
5   B   2013-03-01 08:03:00 7.0
6   B   2013-03-01 08:04:30 9.0
7   B   2013-03-01 08:06:00 9.0

它将使用最后观察到的值来填充NaNs

如果您希望插入这些值,而不仅仅是填补空白,请使用transform(pd.Series.interpolate) 组合。 transform 将在每个组上应用 interpolate() 函数。尝试以更高的频率(比如 10 秒)重新采样,您会发现两种方法之间的巨大差异。

df = df.set_index('timestamp').groupby('Kind').resample('1.5Min').mean().transform(pd.Series.interpolate).reset_index()

Out[2]:

    Kind    timestamp       Values
0   A   2013-03-01 08:00:00 1.0
1   A   2013-03-01 08:01:30 1.5
2   A   2013-03-01 08:03:00 2.0
3   A   2013-03-01 08:04:30 5.0
4   B   2013-03-01 08:01:30 4.5
5   B   2013-03-01 08:03:00 7.0
6   B   2013-03-01 08:04:30 8.0
7   B   2013-03-01 08:06:00 9.0

【讨论】:

【参考方案4】:
df = df.set_index('timestamp') # Set your index.
df.index = df.index.astype('datetime64') # Set to DatetimeIndex (Index doesn't work with resample)
df.resample('5Min').mean() # Do the actual resampling.

这将返回一个包含 2 行的数据框,如您所料:

                    Values
timestamp                  
2013-03-01 08:00:00   1.875
2013-03-01 08:05:00   4.000

您的“种类”列已被删除,因为取字符的意思没有意义。如果您想保留它,则必须引入新规则(例如,为给定时间段分配最常见的字符)。

【讨论】:

以上是关于基于列标准的熊猫数据框重采样的主要内容,如果未能解决你的问题,请参考以下文章

按列索引熊猫数据框重命名列

重采样后合并熊猫数据帧

如何理解熊猫重采样方法中的封闭和标签参数?

熊猫结合了滚动和重采样

熊猫时间序列重采样和插值一起

带有熊猫重采样的额外箱