Я пытаюсь вычислить расстояния между столбцом и его задержкой (смещением) для групп в кадре данных Pandas. Группы должны быть отсортированы так, чтобы сдвиг был на один шаг раньше. Стандартный способ сделать это - .groupby()
(он же Split), затем .apply()
с функцией расстояния по каждой группе, а затем воссоединиться с .concat()
. Это работает нормально, но только когда я не сортирую явно сгруппированный фрейм данных. когда я сортирую сгруппированный фрейм данных, я получаю сообщение об ошибке на этапе присоединения.
Вот мой пример кода, для которого мне удалось воспроизвести неожиданное поведение:
import pandas as pd
def dist_apply(group):
# when commented out, this code will run to completion (!)
group.sort_values(by='T',inplace=True)
group['shift'] = group['Y'].shift()
group['dist'] = group['Y'] - group['shift']
return group
df = pd.DataFrame(pd.DataFrame({'X': ['A', 'B', 'A', 'B', 'A', 'B'], 'T': [0.9, 0.8, 0.7, 0.9, 0.8, 0.7], 'Y': [7, 1, 8, 3, 9, 5]}))
print(df)
# split
df_g = df.groupby(['X'])
# apply
df_g = df_g.apply(dist_apply)
print(df_g)
# rejoin
df = pd.concat([df,df_g],axis=1)
print(df)
Когда код который сортирует сгруппированный фрейм данных, закомментированный, затем код печатает это, что ожидается:
X T Y
0 A 0.9 7
1 B 0.8 1
2 A 0.7 8
3 B 0.9 3
4 A 0.8 9
5 B 0.7 5
X T Y shift dist
0 A 0.9 7 NaN NaN
1 B 0.8 1 NaN NaN
2 A 0.7 8 7.0 1.0
3 B 0.9 3 1.0 2.0
4 A 0.8 9 8.0 1.0
5 B 0.7 5 3.0 2.0
X T Y X T Y shift dist
0 A 0.9 7 A 0.9 7 NaN NaN
1 B 0.8 1 B 0.8 1 NaN NaN
2 A 0.7 8 A 0.7 8 7.0 1.0
3 B 0.9 3 B 0.9 3 1.0 2.0
4 A 0.8 9 A 0.8 9 8.0 1.0
5 B 0.7 5 B 0.7 5 3.0 2.0
С помощью линии сортировки трассировка выглядит так:
Traceback (most recent call last):
File "test.py", line 19, in <module>
df = pd.concat([df,df_g],axis=1)
File "/Users/me/miniconda3/lib/python3.7/site-packages/pandas/core/reshape/concat.py", line 229, in concat
return op.get_result()
File "/Users/me/miniconda3/lib/python3.7/site-packages/pandas/core/reshape/concat.py", line 420, in get_result
indexers[ax] = obj_labels.reindex(new_labels)[1]
File "/Users/me/miniconda3/lib/python3.7/site-packages/pandas/core/indexes/multi.py", line 2236, in reindex
target = MultiIndex.from_tuples(target)
File "/Users/me/miniconda3/lib/python3.7/site-packages/pandas/core/indexes/multi.py", line 396, in from_tuples
arrays = list(lib.tuples_to_object_array(tuples).T)
File "pandas/_libs/lib.pyx", line 2287, in pandas._libs.lib.tuples_to_object_array
TypeError: object of type 'int' has no len()
Сортировка, но не работает concat выводит мне это для df_g:
X T Y shift dist
X
A 2 A 0.7 8 NaN NaN
4 A 0.8 9 8.0 1.0
0 A 0.9 7 9.0 -2.0
B 5 B 0.7 5 NaN NaN
1 B 0.8 1 5.0 -4.0
3 B 0.9 3 1.0 2.0
, которое показывает, что оно сгруппировано иначе, чем печать df_g без сортировки (см. выше), но не ясно, как происходит сбой concat в этом случае.
update : я решил, что решил эту проблему, переименовав поврежденный столбец (в данном случае 'X') и также используя .reset_index()
на сгруппированном кадре данных перед объединением.
df_g.columns = ['X_g','T','Y','shift','dist']
df = pd.concat([df,df_g.reset_index()],axis=1)
работает как положено, и печатает это:
X T Y X level_1 X_g T Y shift dist
0 A 0.9 7 A 2 A 0.7 8 NaN NaN
1 B 0.8 1 A 4 A 0.8 9 8.0 1.0
2 A 0.7 8 A 0 A 0.9 7 9.0 -2.0
3 B 0.9 3 B 5 B 0.7 5 NaN NaN
4 A 0.8 9 B 1 B 0.8 1 5.0 -4.0
5 B 0.7 5 B 3 B 0.9 3 1.0 2.0
Но если присмотреться, этот столбец показывает, что слияние выполнено неправильно:
1 B 0.8 1 A 4 A 0.8 9 8.0 1.0
Я использую Ма c OSX с Python 3.7.6 | упаковано в conda-forge | (по умолчанию, 7 января 2020 г., 22:05:27)
Pandas 0.24.2 + Numpy 1.17.3, а также попытались обновить до Pandas 0.25.3 и Numpy 1.17.5 с тем же результатом.