Как сделать основанную на дате цветную полосу на основе серии df.idxmax? - PullRequest
0 голосов
/ 01 февраля 2019

Python начинающий / первый постер здесь.

У меня проблемы с добавлением цветных полос на графики рассеяния.У меня есть два типа графиков: один показывает все данные с цветовой кодировкой по дате, а другой показывает только максимальные значения моих данных с цветовой кодировкой по дате.В первом случае я могу использовать df.index (который является datetime) для создания моей цветовой шкалы, но во втором случае я использую df2 ['col']. Idxmax для генерации цветов, потому что мой df2 является dfОбъект .groupby, который я использую для создания дневных максимумов в моих данных, и у него нет доступного индекса.

Для первого типа графика мне удалось сгенерировать основанную на дате цветную полосу с приведенным ниже кодом, собранным из онлайн-примеров:

fig, ax = plt.subplots(1,1, figsize=(20,20))

smap=plt.scatter(df.col1, df.col2, s=140, 
             c=[date2num(i.date()) for i in df.index],
             marker='.')

cb = fig.colorbar(smap, orientation='vertical',
              format=DateFormatter('%d %b %y'))  

Однако для второго типаplot, где я пытаюсь использовать df2 ['col']. idxmax для создания ряда дат вместо df.index, следующее не работает:

for n in cols1:
    for m in cols2:
        fig, ax = plt.subplots(1,1, figsize=(15,15))

        maxTimes=df2[n].idxmax()
        PlottableTimes=maxTimes.dropna() #some NaNs in the 
        #.idxmax series were giving date2num trouble

        smap2=plt.scatter(df2[n].max(), df2[m].max(),
             s=160, c=[date2num(i.date()) for i in PlottableTimes], 
             marker='.')

        cb2 = fig.colorbar(smap2, orientation='vertical',
                      format=DateFormatter('%d %b %y'))  

        plt.show()

Ошибка: 'length of rgbaпоследовательность должна быть либо 3, либо 4 '

Поскольку ошибка была связана с аргументом color, я отдельно проверил вывод аргументов color (то есть c =) в соответствующих командах построения, и оба выглядят одинаководля меня, поэтому я не могу понять, почему один цветовой аргумент работает, а другой нет:

тот, который работает:

[736809.0, 736809.0, 736809.0, 736809.0, 736809.0, 736809.0, 736809.0, 736809.0, 736809.0, 736809.0, ...]

тот, который не работает:

[736845.0, 736846.0, 736847.0, 736848.0, 736849.0, 736850.0, 736851.0, 736852.0, 736854.0, ...]

Есть предложения или объяснения?Я использую Python 3.5.2.Заранее спасибо, что помогли мне понять это.

Редактировать 1: Я сделал следующий пример для изучения другими, и в процессе понял, что суть проблемы отличается от моего первого вопроса.Приведенный ниже код работает так, как я хочу:

df=pd.DataFrame(np.random.randint(low=0, high=10, size=(169, 8)), 
            columns=['a', 'b', 'c', 'd', 'e','f','g','h']) #make sample data
date_rng = pd.date_range(start='1/1/2018', end='1/8/2018', freq='H')
df['i']=date_rng
df = df.set_index('i') #get a datetime index
df['ts']=date_rng #get a datetime column to group by

from pandas import Grouper
df2=df.groupby(Grouper(key='ts', freq='D'))

for n in ['a','b','c','d']: #now make some plots
for m in ['e','f','g','h']:
    print(m)
    print(n)

    fig, ax = plt.subplots(1,1, figsize=(5,5))
    maxTimes=df2[n].idxmax()
    PlottableTimes=maxTimes.dropna()

    smap=plt.scatter(df2[n].max(), df2[m].max(), s=160, 
                     c=[date2num(i.date()) for i in PlottableTimes], 
                     marker='.')
    cb = fig.colorbar(smap, orientation='vertical',
                      format=DateFormatter('%d %b %y'))  
    plt.show()

Единственное различие между моими реальными данными и этим примером состоит в том, что в моих реальных данных разбросано много NaN.Итак, я думаю, что что-то идет не так, что аргумент 'c =' недостаточно длинный, чтобы команда построения могла интерпретировать его как охватывающий весь диапазон дат ...?Например, если я вручную введу выходные данные команды c =, я получу следующий код, который также работает:

for n in ['a','b','c','d']:
    for m in ['e','f','g','h']:
        print(m)
        print(n)

        fig, ax = plt.subplots(1,1, figsize=(5,5))
        maxTimes=df2[n].idxmax()
        PlottableTimes=maxTimes.dropna()

        smap=plt.scatter(df2[n].max(), df2[m].max(), s=160, 
                     c=[736809.0, 736810.0, 736811.0, 736812.0, 736813.0, 736814.0, 736815.0, 736816.0], 
                     marker='.')
        cb = fig.colorbar(smap, orientation='vertical',
                      format=DateFormatter('%d %b %y'))  
        plt.show()

Но, если я укороту массив c = на некоторое количество, для эмуляции чего-либопроисходит в моем коде, когда NaNs удаляются из idxmax, это дает ту же ошибку, которую я вижу:

for n in ['a','b','c','d']:
    for m in ['e','f','g','h']:
        print(m)
        print(n)

        fig, ax = plt.subplots(1,1, figsize=(5,5))
        maxTimes=df2[n].idxmax()
        PlottableTimes=maxTimes.dropna()

        smap=plt.scatter(df2[n].max(), df2[m].max(), s=160, 
                     c=[736809.0, 736810.0, 736811.0, 736812.0, 736813.0, 736814.0], 
                     marker='.')
        cb = fig.colorbar(smap, orientation='vertical',
                      format=DateFormatter('%d %b %y'))  
        plt.show()

Таким образом, это означает, что реальный вопрос заключается в следующем: как я могу получить столбец группировщика после группировки изобъект groupby, когда ни один из столбцов не может быть захвачен с помощью df2.col?Я хотел бы иметь возможность взять 'ts' из следующего и использовать его в качестве цветовых данных вместо использования idxmax:

df2['a'].max()

ts
2018-01-01    9
2018-01-02    9
2018-01-03    9
2018-01-04    9
2018-01-05    9
2018-01-06    9
2018-01-07    9
2018-01-08    8
Freq: D, Name: a, dtype: int64

1 Ответ

0 голосов
/ 03 февраля 2019

По сути, ваш Grouper вызов аналогичен индексации в столбце даты и времени и вызову pandas.DataFrame.resample с указанием функции агрегирования:

df.set_index('ts').resample('D').max()
#             a  b  c  d  e  f  g  h
# ts                                
# 2018-01-01  9  9  8  9  9  9  9  9
# 2018-01-02  9  9  9  9  9  9  9  9
# 2018-01-03  9  9  9  9  9  9  9  9
# 2018-01-04  9  9  9  9  9  9  9  9
# 2018-01-05  9  9  9  9  9  9  9  9
# 2018-01-06  9  9  9  8  9  9  9  9
# 2018-01-07  9  9  9  9  9  9  9  9
# 2018-01-08  2  8  6  3  1  3  2  7

Следовательно,возвращаемое значение df2['a'].max() - это объект Pandas Resampler, очень похожий на серию Pandas и, следовательно, содержит свойство индекса, которое вы можете использовать для спецификации цветовой шкалы:

df['a'].max().index

# DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
#                '2018-01-05', '2018-01-06', '2018-01-07', '2018-01-08'],
#               dtype='datetime64[ns]', name='ts', freq='D')

Оттуда вы можете перейти в date2num без понимания списка:

date2num(df2['a'].max().index)

# array([736695., 736696., 736697., 736698., 736699., 736700., 736701., 736702.])

В целом, просто используйте выше в цикле без необходимости maxTimes или PlottableTimes :

fig, ax = plt.subplots(1, 1, figsize = (5,5))

smap = plt.scatter(df2[n].max(), df2[m].max(), s = 160, 
                   c = date2num(df2[n].max().index), 
                   marker = '.')
cb = fig.colorbar(smap, orientation = 'vertical',
                  format = DateFormatter('%d %b %y'))  
...