2013-07-17 2 views
10

У меня есть панд dataframe вроде этого:Панды dataframe: Проверьте, если данные монотонно убывающая

Balance  Jan  Feb  Mar  Apr 
0 9.724135 0.389376 0.464451 0.229964 0.691504 
1 1.114782 0.838406 0.679096 0.185135 0.143883 
2 7.613946 0.960876 0.220274 0.788265 0.606402 
3 0.144517 0.800086 0.287874 0.223539 0.206002 
4 1.332838 0.430812 0.939402 0.045262 0.388466 

Я хотел бы сгруппировать строки, выясняя, если значение от января до апреля монотонно убывает (как в строках с индексом 1 и 3) или нет, а затем складывайте остатки для каждой группы, т. е. в конце я хотел бы получить два числа (1.259299 для уменьшения временного ряда и 18.670919 для остальных).

Я думаю, что если бы я мог добавить столбец «уменьшается» containg booleans, я мог бы делать суммы, используя группу pandas, но как мне создать этот столбец?

Спасибо, Anne

+0

Вы думаете о столбце булевых чисел за каждый месяц? У вас есть переход от уменьшения к увеличению в разных строках. – TomAugspurger

+0

Ahh nevermind. Вы говорите об уменьшении месяца в месяц. Через колонны. – TomAugspurger

ответ

9

Вы можете использовать одну из is_monotonic функций из Algos:

In [10]: months = ['Jan', 'Feb', 'Mar', 'Apr'] 

In [11]: df.loc[:, months].apply(lambda x: pd.algos.is_monotonic_float64(-x)[0], 
             axis=1) 
Out[11]: 
0 False 
1  True 
2 False 
3  True 
4 False 
dtype: bool 

is_monotonic The проверяет, является ли массив это убывающей отсюда -x.values.

(Это, кажется, значительно быстрее, чем решение Тома, даже используя небольшой DataFrame при условии.)

+2

@TomAugspurger Я думаю, что слово, которое вы ищете, «пандастическое» ... \ * ahem \ *. –

+0

Спасибо, Энди, это прекрасно работает. У меня есть немного глупый вопрос - я пытался найти документацию по функции is_monotonic, и я не могу найти ни одной онлайн-версии. У вас есть ссылка? – Anne

+0

Другой вопрос - могу ли я просто написать '-x' вместо' -x.values' в 'df.loc [:, months] .apply (lambda x: pd.algos.is_monotonic_float64 (-x.значения) [0], ось = 1) '? Я попробовал, и это * казалось * работать. – Anne

5
months = ['Jan', 'Feb', 'Mar', 'Apr'] 

транспозиции, так что мы можем использовать diff метод (который не принимает ось аргумента). Заполните первую строку (январь) 0. В противном случае это NaN.

In [77]: df[months].T.diff().fillna(0) <= 0 
Out[77]: 
     0  1  2  3  4 
Jan True True True True True 
Feb False True True True False 
Mar True True False True True 
Apr False True True True False 

Чтобы проверить, монотонно ли оно уменьшается, используйте метод .all(). По умолчанию это проходит по оси 0, строки (месяцы).

In [78]: is_decreasing = (df[months].T.diff().fillna(0) <= 0).all() 

In [79]: is_decreasing 
Out[79]: 
0 False 
1  True 
2 False 
3  True 
4 False 
dtype: bool 

In [80]: df['is_decreasing'] = is_decreasing 

In [81]: df 
Out[81]: 
    Balance  Jan  Feb  Mar  Apr is_decreasing 
0 9.724135 0.389376 0.464451 0.229964 0.691504   False 
1 1.114782 0.838406 0.679096 0.185135 0.143883   True 
2 7.613946 0.960876 0.220274 0.788265 0.606402   False 
3 0.144517 0.800086 0.287874 0.223539 0.206002   True 
4 1.332838 0.430812 0.939402 0.045262 0.388466   False 

И как вы предложили, мы можем GroupBy is_decreasing и сумму:

In [83]: df.groupby('is_decreasing')['Balance'].sum() 
Out[83]: 
is_decreasing 
False   18.670919 
True    1.259299 
Name: Balance, dtype: float64 

Пришло такие времена, когда я люблю панд.

0

Панды 0,19 добавил общественный Series.is_monotonic API (как уже упоминалось, algos модуль без документов и не гарантируется держать.) ,

Есть также is_monotonic_increasing и is_monotonic_decreasing. Все 3 не являются строгими (т. Е. is_monotonic_decreasing проверяют, уменьшается ли последовательность или), но вы можете комбинировать их с is_unqiue, если вам нужна строгость.

my_df = pd.DataFrame({'A':[1,2,3],'B':[1,1,1],'C':[3,2,1]}) 
my_df 
Out[32]: 
    A B C 
0 1 1 3 
1 2 1 2 
2 3 1 1 

my_df.apply(lambda x: x.is_monotonic) 
Out[33]: 
A  True 
B  True 
C False 
dtype: bool 
Смежные вопросы