【问题标题】:pandas selecting max and min simultaneously熊猫同时选择最大值和最小值
【发布时间】:2019-11-08 01:18:11
【问题描述】:

给一个这样的数据框:

   count        date location  type
0    100  2018-01-01    site1  high
1     10  2018-01-01    site2   low
2     11  2018-01-01    site3   low
3    101  2018-01-03    site2  high
4    103  2018-01-03    site2  high
5     15  2018-01-03    site3   low

我需要找到每天的最高和最低计数(在 mm-dd 格式中,年份无关紧要)。我正在寻找的结果是这样的:

                count       date location
month-day type                           
01-01     high    100 2018-01-01    site1
          low      10 2018-01-01    site2
01-03     high    103 2018-01-03    site2
          low      15 2018-01-03    site3

我有一个可行的方法,但我确信它可以被清理掉。这是我目前所拥有的:

df = pd.DataFrame({'date':['2018-01-01', '2018-01-01', '2018-01-01', '2018-01-03', '2018-01-03', '2018-01-03'],
                   'location':['site1', 'site2', 'site3', 'site2', 'site2', 'site3'], 
                   'type':['high', 'low', 'low', 'high', 'high', 'low'], 
                   'count':[100, 10, 11, 101, 103, 15]})

df['date'] = pd.to_datetime(df['date'])
df['month-day'] = df['date'].apply(lambda x: x.strftime('%m-%d')) 

maxCount = df.loc[df.groupby(['month-day']['type'=='high'])['count'].idxmax()]
minCount = df.loc[df.groupby(['month-day']['type'=='low'])['count'].idxmin()]

df = maxCount.merge(minCount, how='outer')
df.set_index(['month-day', 'type'], inplace=True)
df.sort_index(inplace=True)

这些最终将用作 matplotlib 的输入,以图表计数与月日的低位和高位,因此将它们分开而不是将它们重新组合在一起实际上可能是有意义的,但有没有更好的方法来做这个?特别是 groupby 似乎与][ 有点不确定,但它确实有效。我唯一关心的是月日、类型和计数(并且类型只需要知道它是低还是高,所以如果我使用一个专门的系列来表示低,一个用于高,我就不需要保留输入一次我输入月日并计算在适当的系列中)。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    由于您已经指定了高点和低点,因此您想要做的事情变得复杂。你需要考虑这些吗? (一天的最大值是否标记为low?) 如果没有,您可以使用以下简单的方法:

    df.groupby(['month-day']).agg({ 'count': ['min', 'max'] })                                                                                                                                         
    

    这会给你这个:

              count     
                min  max
    month-day           
    01-01        10  100
    01-03        15  103
    

    【讨论】:

    • 这正是我所需要的。我正在使用的数据已经有明确定义的高值和低值(lowhigh),但如果有任何情况下标记为 low 但实际上是当天的最大值,反之亦然,这是数据中的错误。我试图解决的问题的要点是在有多个站点时找到每天的绝对最小值和最大值,每个站点都报告自己的最小值和最大值。我看不到任何这不能满足我需要的情况。
    • 我猜一个极端情况是,如果一个站点的最低 high 低于另一个站点的最高 low,但对于我正在使用的内容,我认为这不太可能。
    【解决方案2】:

    你的逻辑不是很清楚:应该包括type 吗?根据您的尝试,我将假设是的:

    # groupby
    group = df.groupby('month-day')['count']
    
    # create your min and max logic for boolean indexing
    min_log = ((df['count'] == group.transform(min)) & (df['type'] == 'low'))
    max_log = ((df['count'] == group.transform(max)) & (df['type'] == 'high'))
    
    # boolean indexing to filter df
    df[ min_log | max_log]
    
            date location  type  count month-day
    0 2018-01-01    site1  high    100     01-01
    1 2018-01-01    site2   low     10     01-01
    4 2018-01-03    site2  high    103     01-03
    5 2018-01-03    site3   low     15     01-03
    

    【讨论】:

      【解决方案3】:

      你可以试试aggstacklocset_index

      s = pd.to_datetime(df.date).dt.strftime('%m-%d')
      m = df.groupby(s)['count'].agg(['idxmax', 'idxmin']).stack()
      df_out = df.loc[m].set_index([m.index.droplevel(1), 'type'])
      
      Out[127]:
                        date location  count
      date  type
      01-01 high  2018-01-01    site1    100
            low   2018-01-01    site2     10
      01-03 high  2018-01-03    site2    103
            low   2018-01-03    site3     15
      

      【讨论】:

        猜你喜欢
        • 2020-04-28
        • 2017-07-25
        • 2018-06-09
        • 1970-01-01
        • 2017-08-27
        • 2020-09-09
        • 1970-01-01
        • 2019-02-09
        • 2017-03-04
        相关资源
        最近更新 更多