Я пытаюсь создать новый столбец в кадре данных на основе пар информации и его предыдущих значений. Хотя код, который я запускаю, является правильным и дает нужные мне результаты, он очень медленный, когда я запускаю его на большом фрейме данных. Поэтому я не использую всю мощность Python для этой задачи. Есть ли более эффективный и быстрый способ сделать это в Python?.
Чтобы представить вас в контексте, позвольте мне немного объяснить вам, что я ищу:
У меня есть датафрейм, который описывает результаты соревнований, где для каждой 'даты' вы можете увидеть 'type' , который участвовал в соревновании, и его счет называется 'xx' .
Что мой код делает, чтобы получить разницу в баллах «xx» между «типом» для каждой «даты», а затем получить сумму различий результатов предыдущих соревнований, что для всех типов конкурировать друг с другом было в прошлом ('win_comp_past_difs').
Ниже вы можете увидеть данные и модель с ее выводом.
## I. DATA AND MODEL ##
I.1. Данные
import pandas as pd
import numpy as np
idx = [np.array(['Jan-18', 'Jan-18', 'Feb-18', 'Mar-18', 'Mar-18', 'Mar-18','Mar-18', 'Mar-18', 'May-18', 'Jun-18', 'Jun-18', 'Jun-18','Jul-18', 'Aug-18', 'Aug-18', 'Sep-18', 'Sep-18', 'Oct-18','Oct-18', 'Oct-18', 'Nov-18', 'Dec-18', 'Dec-18',]),np.array(['A', 'B', 'B', 'A', 'B', 'C', 'D', 'E', 'B', 'A', 'B', 'C','A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'A', 'B', 'C'])]
data = [{'xx': 1}, {'xx': 5}, {'xx': 3}, {'xx': 2}, {'xx': 7}, {'xx': 3},{'xx': 1}, {'xx': 6}, {'xx': 3}, {'xx': 5}, {'xx': 2}, {'xx': 3},{'xx': 1}, {'xx': 9}, {'xx': 3}, {'xx': 2}, {'xx': 7}, {'xx': 3}, {'xx': 6}, {'xx': 8}, {'xx': 2}, {'xx': 7}, {'xx': 9}]
df = pd.DataFrame(data, index=idx, columns=['xx'])
df.index.names=['date','type']
df=df.reset_index()
df['date'] = pd.to_datetime(df['date'],format = '%b-%y')
df=df.set_index(['date','type'])
df['xx'] = df.xx.astype('float')
Что выглядит следующим образом:
xx
date type
2018-01-01 A 1.0
B 5.0
2018-02-01 B 3.0
2018-03-01 A 2.0
B 7.0
C 3.0
D 1.0
E 6.0
2018-05-01 B 3.0
2018-06-01 A 5.0
B 2.0
C 3.0
2018-07-01 A 1.0
2018-08-01 B 9.0
C 3.0
2018-09-01 A 2.0
B 7.0
2018-10-01 C 3.0
A 6.0
B 8.0
2018-11-01 A 2.0
2018-12-01 B 7.0
C 9.0
I.2. Модель ( очень медленно в большом фрейме данных )
# get differences of pairs, useful for win counts and win_difs
def get_diff(x):
teams = x.index.get_level_values(1)
tmp = pd.DataFrame(x[:,None]-x[None,:],columns = teams.values,index=teams.values).stack()
return tmp[tmp.index.get_level_values(0)!=tmp.index.get_level_values(1)]
new_df = df.groupby('date').xx.apply(get_diff).to_frame()
# group by players
groups = new_df.groupby(level=[1,2])
# sum function
def cumsum_shift(x):
return x.cumsum().shift()
# assign new values
df['win_comp_past_difs'] = groups.xx.apply(cumsum_shift).sum(level=[0,1])
Ниже вы можете увидеть, как выглядит вывод модели:
xx win_comp_past_difs
date type
2018-01-01 A 1.0 0.0
B 5.0 0.0
2018-02-01 B 3.0 NaN
2018-03-01 A 2.0 -4.0
B 7.0 4.0
C 3.0 0.0
D 1.0 0.0
E 6.0 0.0
2018-05-01 B 3.0 NaN
2018-06-01 A 5.0 -10.0
B 2.0 13.0
C 3.0 -3.0
2018-07-01 A 1.0 NaN
2018-08-01 B 9.0 3.0
C 3.0 -3.0
2018-09-01 A 2.0 -6.0
B 7.0 6.0
2018-10-01 C 3.0 -10.0
A 6.0 -10.0
B 8.0 20.0
2018-11-01 A 2.0 NaN
2018-12-01 B 7.0 14.0
C 9.0 -14.0
На тот случай, если вам трудно понять, что делает пользовательская функция (def), позвольте мне объяснить вам ее ниже .
Для этой компании я буду работать с одной группой группы данных в фрейме данных.
Ниже вы увидите объяснение того, как работает пользовательская функция.
## II. EXPLANATION OF THE USER-DEFINED FUNCTION ##
Итак, вы увидите, как работает пользовательская функция позвольте мне выбрать конкретную c группу groupby.
II.1 Выбор определенной c группы
gb = df.groupby('date')
gb2 = gb.get_group((list(gb.groups)[2]))
, которая выглядит следующим образом:
xx
date type
2018-03-01 A 2.0
B 7.0
C 3.0
D 1.0
E 6.0
II.2 Создание списка участников (команд) '
teams = gb2.index.get_level_values(1)
II.3 Создание кадра данных разности' xx 'Между' типом
df_comp= pd.DataFrame(gb2.xx[:,None]-gb2.xx[None,:],columns = teams.values,index=teams.values)
Что выглядит следующим образом:
A B C D E
A 0.0 -5.0 -1.0 1.0 -4.0
B 5.0 0.0 4.0 6.0 1.0
C 1.0 -4.0 0.0 2.0 -3.0
D -1.0 -6.0 -2.0 0.0 -5.0
E 4.0 -1.0 3.0 5.0 0.0
С этого момента я использую функцию stack () в качестве промежуточного шага go вернуться к исходному кадру данных. В остальном вы можете следить за этим в I. ДАННЫЕ И МОДЕЛЬ.
Если бы вы могли разработать код, чтобы сделать его более эффективным и быстрее выполнять, я был бы очень признателен.