Pandas groupby:返回不同的索引

时间:2018-01-16 11:42:26

标签: python pandas grouping

Versions:
* Pandas 0.21.0
* Python 2.7.12

我在Pandas中看到这种奇怪的行为:根据数据框和排序,groupby返回不同的结果:

import pandas as pd
from datetime import datetime

df1 = pd.DataFrame({'dtime': [datetime(2017,1,1,1,5), datetime(2017,1,1,1,20)],
                   'val1': [11, None],
                   'val2': [None, 31]
                  })

df2 = pd.DataFrame({'dtime': [datetime(2017,1,1,1,5), datetime(2017,1,1,1,20)],
                   'val1': [11, None],
                   'val2': [31, None]
                  })



df1b = df1.melt("dtime").dropna().set_index("dtime")
df2b = df2.melt("dtime").dropna().set_index("dtime")

r1a = df1b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=True))
r1b = df1b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=False))

r2a = df2b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=True))
r2b = df2b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=False))

print "\n--- df1 ascending sort ---------------\n", r1a
print "\n--- df1 descending sort SHOULD IT ALWAYS BE LIKE THIS? --------------\n", r1b
print "\n--- df2 ascending sort ---------------\n", r2a
print "\n--- df2 descending sort --------------\n", r2b

返回

--- df1 ascending sort ---------------
dtime
2017-01-01 01:05:00    11.0
2017-01-01 01:20:00    31.0
Name: value, dtype: float64

--- df1 descending sort SHOULD IT ALWAYS BE LIKE THIS? --------------
dtime                dtime              
2017-01-01 01:00:00  2017-01-01 01:20:00    31.0
                     2017-01-01 01:05:00    11.0
Name: value, dtype: float64

--- df2 ascending sort ---------------
dtime
2017-01-01 01:05:00    11.0
2017-01-01 01:05:00    31.0
Name: value, dtype: float64

--- df2 descending sort --------------
dtime
2017-01-01 01:05:00    31.0
2017-01-01 01:05:00    11.0
Name: value, dtype: float64

为什么df1 descending sort会返回分组的参考时间(2017-01-01 01:00:00),而其他组中缺少参考时间? 我希望所有分组都将参考时间作为多索引返回,无一例外。

我在github pandas #18908创建了一个问题,但在一个月内没有有用的答案。我想了解这只是一个演示问题还是一个可能的错误。 我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

在Python 3.5和Pandas 0.22上测试 - 使用略有不同的代码(pd.melt()代替df.melt)。

首先 - 差异的原因。

df1具有两个不同时间戳(01:20:00和01:05:00)的值,其中df2保留的两个观察值都在同一时间戳(01:05:00)。

我不确定原因,但显然反转排序方式的行为确实意味着.values调用包括df1上的分组器时间窗口,因为您将值排序为降序在升序时间指数内。 df2的结果不同,因为时间戳是相同的,因此不需要石斑鱼。您可能已经推断出这一点,如果是这样,请为重复道歉。

建议始终如一地显示您的预期结果

通常在使用pandas.DataFrame.groupby时,我会使用聚合调用来操作数据(max,但sumcount和其他人都可用。如果您希望通过石斑鱼的参考时间来查看您的值,这将是接近它的方法:

这是df1b,对观察值有多个时间戳:

In []: df1b.groupby([pd.Grouper(freq="1h"), df1b.index, "variable"])\
       .max().sort_values("value", ascending=False)
Out[]:
                                                  value
dtime               dtime               variable
2017-01-01 01:00:00 2017-01-01 01:20:00 val2       31.0
                    2017-01-01 01:05:00 val1       11.0    

...和df2b的方法相同:

In []: df2b.groupby([pd.Grouper(freq="1h"), df2b.index, "variable"])\
       .max().sort_values("value", ascending=False)
Out[]:
                                                  value
dtime               dtime               variable
2017-01-01 01:00:00 2017-01-01 01:05:00 val2       31.0
                                        val1       11.0

这有帮助吗?或者我是否错过了使用.values方法的重要性?

免责声明:我不熟悉使用groupby.value,因此您可能会尝试实现我错过的内容。

答案 1 :(得分:2)

这种行为起初是意料之外的,但我不认为这是一个错误。  首先,请注意 ascending=False会导致此行为(请参阅下面的示例)。其次,当调用石斑鱼使得多索引参考时间是多余的(或不必要的)时,它被跳过。当排序的值与时间戳的顺序时会发生这种情况。我看到@Phil Sheard已经提出了一种方法来获得你的预期结果(+1),所以下面我只是扩展行为,为什么我认为pd这样做是明智的。

首先,请注意当我以相反顺序生成df3数据的val时,此行为会在升序搜索中等效发生:

import pandas as pd
from datetime import datetime

df1 = pd.DataFrame({'dtime': [datetime(2017,1,1,1,5), datetime(2017,1,1,1,20)],
                   'val1': [11, None],
                   'val2': [None, 31]
                  })

df2 = pd.DataFrame({'dtime': [datetime(2017,1,1,1,5), datetime(2017,1,1,1,20)],
                   'val1': [11, None],
                   'val2': [31, None]
                  })

df3 = pd.DataFrame({'dtime': [datetime(2017,1,1,1,5), datetime(2017,1,1,1,20)],
                   'val1': [None, 11],
                   'val2': [31, None]
                  })


df1b = df1.melt("dtime").dropna().set_index("dtime")
df2b = df2.melt("dtime").dropna().set_index("dtime")
df3b = df3.melt("dtime").dropna().set_index("dtime")

r1a = df1b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=True))
r1b = df1b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=False))

r2a = df2b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=True))
r2b = df2b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=False))

r3a = df3b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=True))
r3b = df3b.groupby(pd.Grouper(freq="1h")).value.apply(lambda x: x.sort_values(ascending=False))


print("\n--- df1 ascending sort ---------------\n {}".format(r1a))
print("\n--- df1 descending sort SHOULD IT ALWAYS BE LIKE THIS? --------------\n {}".format(r1b))
print("\n--- df2 ascending sort ---------------\n {}".format(r2a))
print("\n--- df2 descending sort --------------\n {}".format(r2b))
print("\n--- df3 ascending sort SHOULD IT ALWAYS BE LIKE THIS? --------------\n {}".format(r3a))
print("\n--- df3 descending sort --------------\n {}".format(r3b))

返回:

--- df1 ascending sort ---------------
 dtime
2017-01-01 01:05:00    11.0
2017-01-01 01:20:00    31.0
Name: value, dtype: float64

--- df1 descending sort SHOULD IT ALWAYS BE LIKE THIS? --------------
 dtime                dtime              
2017-01-01 01:00:00  2017-01-01 01:20:00    31.0
                     2017-01-01 01:05:00    11.0
Name: value, dtype: float64

--- df2 ascending sort ---------------
 dtime
2017-01-01 01:05:00    11.0
2017-01-01 01:05:00    31.0
Name: value, dtype: float64

--- df2 descending sort --------------
 dtime
2017-01-01 01:05:00    31.0
2017-01-01 01:05:00    11.0
Name: value, dtype: float64

--- df3 ascending sort SHOULD IT ALWAYS BE LIKE THIS? --------------
 dtime                dtime              
2017-01-01 01:00:00  2017-01-01 01:20:00    11.0
                     2017-01-01 01:05:00    31.0
Name: value, dtype: float64

--- df3 descending sort --------------
 dtime
2017-01-01 01:05:00    31.0
2017-01-01 01:20:00    11.0
Name: value, dtype: float64

注意当排序值导致时间戳失序时,多索引引用就在那里,否则不存在(因为不必要)。我用两个以上的值(以及其他排列)完成了这个并且行为是相同的。

最终评论如上所述,我认为这不是一个错误。也就是说,我同意你的看法,它不一定是最自然的设计选择,因为它会导致你所发现的奇怪差异。