Более эффективный способ написать это для цикла?

#python #pandas #list #for-loop

Вопрос:

 import pandas as pd

sim = [['Matthew Stafford', 15, 13, 12], ['Dalvin Cook', 18, 16, 17], ['Daniel Jones', 17, 17, 15], ['Joe Mixon', 16, 15, 15]]
col = ['Player', 1 , 2, 3]
NFL_Sim = pd.DataFrame(sim, columns=col)
list = [['Matthew Stafford', 'Dalvin Cook'], ['Daniel Jones', 'Joe Mixon']]
col = ['QB', 'RB']
output_lines = pd.DataFrame(list, columns=col)

for x in range(1, 4):
    output_lines[x] = output_lines.QB.map(NFL_Sim.set_index('Player')[x].to_dict())   output_lines.RB.map(NFL_Sim.set_index('Player')[x].to_dict())

print(output_lines)

                 QB           RB   1   2   3
0  Matthew Stafford  Dalvin Cook  33  29  29
1      Daniel Jones    Joe Mixon  33  32  30
 

Желаемый вывод верен, однако при увеличении масштаба у меня есть тысячи столбцов в кадре данных NFL_Sim, что делает сопоставление чрезвычайно медленным. Есть ли более эффективный способ написать это для цикла? Или сначала преобразуйте output_lines в список? Я действительно не уверен, что лучше.

Комментарии:

1. пожалуйста, опубликуйте ожидаемый выходной кадр данных

2. Прошу прощения, я уже отправил это.

Ответ №1:

Гораздо более динамичный способ с melt :

 >>> x = output_lines.melt(value_name='Player', ignore_index=False).merge(NFL_Sim, on='Player')
>>> output_lines = output_lines.join(x.loc[[*x.index[::2], *x.index[1::2]]].groupby(x.index // 2).sum())
>>> output_lines
                 RB           QB   1   2   3
0  Matthew Stafford  Dalvin Cook  33  29  29
1      Daniel Jones    Joe Mixon  33  32  30
>>> 
 

Комментарии:

1. Ух ты, хотел бы я знать панд больше, чем просто основателей…

2. @Jab Ха-ха! Да, это было сложно 🙂

3. Я знаю достаточно только для того, чтобы быть опасным.]

4. @Jab Ха-ха :П!!!

5. Проверьте почтовый ящик в вашем описании. пожалуйста

Ответ №2:

Во-первых, я предлагаю вам установить индекс NFL_Sim один раз, когда он будет создан. Таким образом, вам не придется делать это дважды внутри цикла.

Во-вторых, если у вас есть список защитников и список бегущих защитников, я предлагаю вам создать две матрицы: одну для защитников и одну для бегущих защитников. Затем вы можете сложить эти два вместе.

 import pandas as pd

sim = [['Matthew Stafford', 15, 13, 12], ['Dalvin Cook', 18, 16, 17], ['Daniel Jones', 17, 17, 15], ['Joe Mixon', 16, 15, 15]]
col = ['Player', 1 , 2, 3]
NFL_Sim = pd.DataFrame(sim, columns=col).set_index('Player')
qbs = ['Matthew Stafford', 'Daniel Jones']
rbs = ['Dalvin Cook', 'Joe Mixon']

qb_scores = NFL_Sim.loc[qbs, :]
rb_scores = NFL_Sim.loc[rbs, :]
# We need to reset the index because otherwise the addition
# of qb_scores and rb_scores will not be compatible; they have
# different indexes
output = qb_scores.reset_index(drop=True)   rb_scores.reset_index(drop=True)
output = output.assign(QB=qbs, RB=rbs)
 

Комментарии:

1. Я попытался запустить этот точный код и получил «Ошибку ключа: «Ни один из [индекса ([«Мэтью Стаффорд», «Далвин Кук»], dtype=»объект»)] не находится в [столбцах]»

2. Я думаю, что это произошло NFL_sim[qbs] потому, что индексация по умолчанию в кадрах данных Pandas предназначена для столбцов. Наверное, так и должно быть NFL_sim.loc[qbs, :] .

3. Я также вижу, что qbs у меня перепутаны списки rbs и. QBS должны быть Мэтью Стаффорд и Дэниел Джонс. RBS должны быть Далвин Кук и Джо Миксон. Я тоже исправил это.

Ответ №3:

Создайте свое отображение, используя ряд: (сопряжение QB и RB выполняется в output_lines, мы хотим использовать позиции индекса для подключения к NFL_Sim)

 mapping = output_lines.T.stack()
mapping = pd.Series(mapping.index.droplevel(0), mapping)
 

Получите сумму по каждой позиции:

 mapping = (NFL_Sim.assign(positions = lambda df: df.Player.map(mapping))
           # we do not need the Player column anymore,
           # since we have our mapping
                 .select_dtypes('number')
                 .groupby('positions')
                 .sum()
           )
 

Переподключите отображение обратно к линиям вывода

 output_lines.join(mapping)

                 QB           RB   1   2   3
0  Matthew Stafford  Dalvin Cook  33  29  29
1      Daniel Jones    Joe Mixon  33  32  30