熊猫同时选择最大值和最小值

时间:2019-11-08 01:18:11

标签: python pandas

给出这样的数据框:

   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似乎对][不太满意,但是它确实起作用。我唯一关心的是月日,类型和计数(并且只需要知道类型是低还是高,因此,如果我使用一个专门的序列来表示低和高,那么我就不需要保留输入一次,然后按月输入日期并按适当的顺序计数)。

3 个答案:

答案 0 :(得分:1)

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

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

哪个会给你这个:

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

答案 1 :(得分:0)

您不清楚逻辑是否正确:应该包含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

答案 2 :(得分:0)

您可以尝试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