Pandas dataframe: проверьте, монотонно ли данные
У меня есть pandas 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
Я хотел бы сгруппировать строки, выясняя, монотонно ли уменьшаются значения от Jan до до Apr (как в строках с индексом 1 и 3) или нет, а затем складывают остатки для каждой группы, то есть в конце Я хотел бы получить два числа (1.259299 для уменьшения временных рядов и 18.670919 для остальных).
Я думаю, что если бы я мог добавить столбец "убывает", то конвейер булевых я мог бы делать суммы с помощью pandas 'groupby, но как бы создать этот столбец?
Спасибо,
Энн
Ответы
Ответ 1
Вы можете использовать одну из функций is_monotonic
из альгос:
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
проверяет, уменьшает ли массив его значение -x.values
.
(Это кажется значительно быстрее, чем решение Tom, даже при использовании небольшого DataFrame.)
Ответ 2
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
И, как вы сказали, мы можем группировать is_decreasing
и sum:
In [83]: df.groupby('is_decreasing')['Balance'].sum()
Out[83]:
is_decreasing
False 18.670919
True 1.259299
Name: Balance, dtype: float64
Это времена, когда я люблю pandas.
Ответ 3
Pandas 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