【问题标题】:Pandas groupby: different indexes returnedPandas groupby:返回不同的索引
【发布时间】:2018-01-16 11:42:26
【问题描述】:
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 创建了一个问题,但在一个月内没有任何有用的答案。我想了解这只是一个演示问题还是一个可能的错误。 我错过了什么吗?

【问题讨论】:

  • 您使用的是哪个版本的 Pandas 和 Python,以防在验证时有所不同?
  • 当然,这可能很重要:Python 2.7.12 和 Pandas 0.21.0
  • 这真的很奇怪,更可能是一个错误
  • 我是否正确地假设我们应该总是读取一个多索引(分组参考时间 + dtime),就像在df1 descending 中一样?我很奇怪没有在结果中阅读它,因为这是我对数据进行分组的主要原因......

标签: python pandas grouping


【解决方案1】:

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

首先 - 差异的原因。

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

我不完全确定为什么,但显然反转排序方式的行为确实意味着 .values 调用包括 df1 上的 grouper 时间窗口,因为您将值排序为在升序时间索引中降序. df2 的结果不同,因为时间戳相同,因此不需要 grouper。你可能已经推断出来了,如果是这样,请原谅重复。

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

通常在使用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,因此您可能正在尝试实现我错过的目标。

【讨论】:

  • 谢谢你,@Phil!始终显示相同结果的提示非常有效。说实话,我还需要了解它为什么会起作用,但我需要一些时间来看看发生了什么。我不需要“插入时间”,只需要“组时间”,所以我将从多索引中删除前者。根据您的说法,在 groupby 之后不显示分组时间是一个可能的错误还是一个可接受的结果?
  • Alex 请看下面我的例子;我认为/希望他们澄清为什么会这样。也就是说,@Phil 的解决方案是可行的方法。
  • @AlexPoca 我个人认为这不是一个错误,因为您的原始方法绕过了使用.groupby 并直接访问值的传统方式。但我只是一个用户,并没有参与这个项目,所以这只是一个意见。我学到了一些新东西,因为我从来没有理由访问结果,所以我在这里也获得了一些东西:)
【解决方案2】:

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

首先,请注意,当我创建一个具有相反顺序的 val 数据的 df3 时,这种行为同样发生在升序搜索中:

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

注意,当排序值导致时间戳乱序时,多索引引用存在,否则不存在(因为不必要)。我已经使用两个以上的值(和其他排列)完成了此操作,并且行为是相同的。

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

【讨论】:

  • 谢谢你,@muskrat。确实很有趣。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-27
  • 2018-09-22
  • 2014-11-15
  • 1970-01-01
  • 2018-08-29
  • 2018-04-17
  • 2014-02-02
相关资源
最近更新 更多