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创建了一个问题,但在一个月内没有有用的答案。我想了解这只是一个演示问题还是一个可能的错误。 我错过了什么吗?
答案 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
,但sum
,count
和其他人都可用。如果您希望通过石斑鱼的参考时间来查看您的值,这将是接近它的方法:
这是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
注意当排序值导致时间戳失序时,多索引引用就在那里,否则不存在(因为不必要)。我用两个以上的值(以及其他排列)完成了这个并且行为是相同的。
最终评论如上所述,我认为这不是一个错误。也就是说,我同意你的看法,它不一定是最自然的设计选择,因为它会导致你所发现的奇怪差异。