Хотите добавить столбец, в котором будет отслеживаться запись каждой команды по игре. У меня есть столбец сезона, в котором помечены каждый сезон и сезон публикации за последние несколько лет.
array(['2012-13', '2013-14', '2014-15', '2015 Post', '2015-16',
'2016 Post', '2016-17', '2017 Post', '2013 Post', '2014 Post'], dtype=object)
Должен ли я использовать groupby для разделения каждого сезона в первую очередь, или это не обязательно. Я пробовал искать везде аналогичный вопрос и ничего не нашел, поэтому не совсем уверен, как даже подойти к этой проблеме. Ваше здоровье!
Date Visitor V_PTS Home H_PTS \
0 2012-10-30 19:00:00 Washington Wizards 84 Cleveland Cavaliers 94
1 2012-10-30 19:30:00 Dallas Mavericks 99 Los Angeles Lakers 91
2 2012-10-30 20:00:00 Boston Celtics 107 Miami Heat 120
3 2012-10-31 19:00:00 Dallas Mavericks 94 Utah Jazz 113
4 2012-10-31 19:00:00 San Antonio Spurs 99 New Orleans Pelicans 95
Attendance Arena Location Capacity \
0 20562 Quicken Loans Arena Cleveland, Ohio 20562
1 18997 Staples Center Los Angeles, California 18997
2 20296 American Airlines Arena Miami, Florida 19600
3 17634 Vivint Smart Home Arena Salt Lake City, Utah 18303
4 15358 Smoothie King Center New Orleans, Louisiana 16867
Yr Arena Opened Season H_Wins H_Losses V_Wins V_Losses
0 1994 2012-13 0 0 0 0
1 1992 2012-13 0 0 0 0
2 1999 2012-13 0 0 0 0
3 1991 2012-13 0 0 0 0
4 1999 2012-13 0 0 0 0
Я знаю, что это не самый питонический способ, но пока я могу охарактеризовать его как выигрыш или проигрыш, используя этот код
nba['Wins'] = np.where(nba['H_PTS']>nba['V_PTS'], 1, 0)
nba['Losses'] = np.where(nba['H_PTS']<nba['V_PTS'], 1, 0)
Есть ли способ заставить его добавлять себя на основе столбца в той же метке сезона?
Оба. Например, первые игры всех команд будут 0-0. В следующей игре, в которой появится Кливленд, я бы хотел показать, что они 1: 0, а если они выиграют эту игру, то 2: 0 в следующей игре и так далее. Также убедитесь, что при смене сезона он снова сбрасывается до 0-0.
Спасибо - я все еще не понимаю, как должен выглядеть результат. Похоже, вам нужны не только общие выигрыши и проигрыши, но и текущий счет. Можете ли вы добавить желаемый результат в сам пост?
Хорошо, обновил. Да, мне нужна промежуточная сумма, а не просто общая сумма. По сути, эта строка всегда будет показывать только их запись на дату начала игры, если это имеет смысл.
Думаю, теперь я понимаю. В будущем попробуйте построить ожидаемый результат так, чтобы он (1) отличался от ввода и (2) действительно показывал желаемое поведение - прямо сейчас он является частью входного фрейма данных, и ни одно из желаемых вами суммирующих действий не выполняется. там.
Потрясающие. Я ценю вашу помощь и отзывы.
Рад помочь, напишу ответ сейчас (подсказка: используйте groupby()
и cumsum()
)
Это займет немного больше времени, чем я ожидал, но ответ будет завтра. Извините за задержку.
Спасибо за помощь, я очень признателен! Это заставляет меня чувствовать себя немного лучше, потому что я застрял на этом сам, ха-ха
Это оказывается сложнее, чем кажется. Определенно есть способы упростить решение, которое я нашел, но я собираюсь изложить его шаг за шагом, чтобы было понятно, что происходит.
Но сначала стоит спросить, почему это сложно. Это похоже на простую проблему groupby()
, используя .cumsum()
для суммирования выигрышей и проигрышей. И если бы вы просто хотели получить результаты для команд гостей, это было бы. Но ваша проблема в том, что вы хотите выиграть на команды, период, независимо от того, в гостях они или дома.
Для этого я предлагаю разбить проблему на несколько этапов (всегда полезно, если у вас есть проблемный код).
Главный ответ
Сначала разделите свои данные на два фрейма данных, один для команд посещения, а другой - для домашних команд:
vdf = nba.set_index(['Season', 'Date', 'Visitor'])
vdf['win'] = np.where(vdf['H_PTS'] < vdf['V_PTS'], 1, 0)
vdf.index.names = ['Season', 'Date', 'Team']
hdf = nba.set_index(['Season', 'Date', 'Home'])
hdf['win'] = np.where(hdf['H_PTS'] > hdf['V_PTS'], 1, 0)
hdf.index.names = ['Season', 'Date', 'Team']
После разделения мы делаем две вещи для каждого фрейма данных. Во-первых, мы создаем столбец win
, используя np.where()
(кстати, отлично питонический. Я бы сказал, просто используйте логическое значение, но это не очень хорошо работает с .cumsum()
). Во-вторых, мы переименовываем индекс, поэтому вместо посетителей и домашних команд мы говорим только о командах. Это важно, потому что теперь мы собираемся снова объединить эти фреймы данных в один:
df = pd.concat([vdf, hdf])
df['loss'] = 1 - df.win
df = df.sort_index(level=['Date'])
gr = df.groupby(level=['Season', 'Team'])
Мы можем рассчитать loss
для команды как простую инверсию win
. Затем мы сортируем по Date
- поскольку ни одна команда не может играть в две игры одновременно, это должно быть нормально. Затем мы сгруппируем по Season
и Team
, так как это группа, по которой вы хотите подсчитывать результаты.
Теперь довольно просто суммировать выигрыши и проигрыши:
df['wins'] = gr.win.apply(lambda g: g.shift().cumsum().fillna(0))
df['losses'] = gr.loss.apply(lambda g: g.shift().cumsum().fillna(0))
Если вы хотите получить результаты, включая текущую игру, вы можете просто использовать .cumsum()
. Но поскольку вам нужны результаты, как в предыдущей игре, нам нужно использовать .shift()
, а затем заполнить (теперь пустую) первую строку нулем.
Но теперь у нас возникла проблема: команды хозяев и посетителей находятся в разных рядах! Чтобы исправить это, мы снова разделили их на отдельные фреймы данных и переименовали столбцы, чтобы было понятно, о посетителях мы говорим или о домашних записях.
vdf = df.dropna(subset=['Home'])[['wins', 'losses']].rename(columns=lambda c: 'V_' + c)
hdf = df.dropna(subset=['Visitor'])[['wins', 'losses']].rename(columns=lambda c: 'H_' + c)
Последний реальный шаг - это объединение обратно в основной фрейм данных на основе названий команд Visitor
и Home
.
nba = nba.merge(vdf.astype(int), left_on=['Season', 'Date', 'Visitor'], right_index=True)
nba = nba.merge(hdf.astype(int), left_on=['Season', 'Date', 'Home'], right_index=True)
Наконец, мы можем (при желании) создать формат W-L
, о котором вы упоминаете в комментариях:
nba['V_winloss'] = nba['V_wins'].astype(str) + '-' + nba['V_losses'].astype(str)
nba['H_winloss'] = nba['H_wins'].astype(str) + '-' + nba['H_losses'].astype(str)
Сделанный! Дальнейшее ее упрощение (что определенно можно сделать) оставлено читателю в качестве упражнения.
Весь код в одном месте:
vdf = nba.set_index(['Season', 'Date', 'Visitor'])
vdf['win'] = np.where(vdf['H_PTS'] < vdf['V_PTS'], 1, 0)
vdf.index.names = ['Season', 'Date', 'Team']
hdf = nba.set_index(['Season', 'Date', 'Home'])
hdf['win'] = np.where(hdf['H_PTS'] > hdf['V_PTS'], 1, 0)
hdf.index.names = ['Season', 'Date', 'Team']
df = pd.concat([vdf, hdf])
df['loss'] = 1 - df.win
df['location'] = np.where(pd.notnull(df['Home']), 'h', 'v')
df = df.sort_index(level=['Date'])
gr = df.groupby(level=['Season', 'Team'])
df['wins'] = gr.win.apply(lambda g: g.shift().cumsum().fillna(0))
df['losses'] = gr.loss.apply(lambda g: g.shift().cumsum().fillna(0))
vdf = df.dropna(subset=['Home'])[['wins', 'losses']].rename(columns=lambda c: 'V_' + c)
hdf = df.dropna(subset=['Visitor'])[['wins', 'losses']].rename(columns=lambda c: 'H_' + c)
nba = nba.merge(vdf.astype(int), left_on=['Season', 'Date', 'Visitor'], right_index=True)
nba = nba.merge(hdf.astype(int), left_on=['Season', 'Date', 'Home'], right_index=True)
nba['V_winloss'] = nba['V_wins'].astype(str) + '-' + nba['V_losses'].astype(str)
nba['H_winloss'] = nba['H_wins'].astype(str) + '-' + nba['H_losses'].astype(str)
Пример (и несколько советов)
Всякий раз, когда у вас возникает вопрос, попробуйте создать как образец желаемого ввода, так и желаемого результата, отформатированный таким образом, чтобы респонденты могли скопировать и вставить его прямо в свой код. Этот образец должен продемонстрировать ключевые требования для вашей задачи. В вашем случае это, вероятно, будет включать команду, которая играет как дома, так и на выезде, а также несколько сезонов. Это полезное упражнение еще до того, как вы зададите вопрос - создание тестового стенда с базовыми кейсами позволяет легко проверить, работает ли код, который вы пишете, как задумано.
Я сделал образец фрейма данных, который включает эти функции. Обратите внимание, что я удалил столбцы, которые не имеют значения для рассматриваемой проблемы.
>>> nba
Season Date Visitor Home V_PTS H_PTS
0 1 1 A E 1 2
1 1 2 B E 1 0
2 1 3 C E 1 2
3 1 4 D E 1 0
4 1 5 E A 1 2
5 1 6 E B 1 0
6 1 7 E C 1 2
7 1 8 E D 1 0
8 2 9 A E 1 2
После того, как вы подсчитаете выигрыши и проигрыши (df['losses'] = ...
), вы должны проверить, правильно ли накапливаются результаты команд:
>>> print df[['wins', 'losses']].sort_index(level=['Team', 'Date']).astype(int)
wins losses
Season Date Team
1 1 A 0 0
5 A 0 1
2 9 A 0 0
1 2 B 0 0
6 B 1 0
3 C 0 0
7 C 0 1
4 D 0 0
8 D 1 0
1 E 0 0
2 E 1 0
3 E 1 1
4 E 2 1
5 E 2 2
6 E 2 3
7 E 3 3
8 E 3 4
2 9 E 0 0
Тогда к концу вы получите вот что:
Season Date Visitor Home V_PTS H_PTS V_wins V_losses H_wins \
0 1 1 A E 1 2 0 0 0
1 1 2 B E 1 0 0 0 1
2 1 3 C E 1 2 0 0 1
3 1 4 D E 1 0 0 0 2
4 1 5 E A 1 2 2 2 0
5 1 6 E B 1 0 2 3 1
6 1 7 E C 1 2 3 3 0
7 1 8 E D 1 0 3 4 1
8 2 9 A E 1 2 0 0 0
H_losses V_winloss H_winloss
0 0 0-0 0-0
1 0 0-0 1-0
2 1 0-0 1-1
3 1 0-0 2-1
4 1 2-2 0-1
5 0 2-3 1-0
6 1 3-3 0-1
7 0 3-4 1-0
8 0 0-0 0-0
Вы можете просмотреть его, чтобы убедиться, что он соответствует вашему желанию.
Удивительный!! Не думаю, что я бы вообще туда попал без тебя. Отличное описание и пошаговое руководство по процессу. Я обязательно перечитаю несколько раз, чтобы лучше понять концепции. Также цените ваши отзывы для будущих публикаций. Большое вам спасибо еще раз !!
Я знаю, как может быть неприятно смотреть на «простую» проблему и не иметь возможности ее решить. Я уверен, что вы придумаете гораздо более простой способ справиться с этим в будущем и, надеюсь, однажды опубликуете здесь лучший ответ. А пока рад, что помог!
Не могли бы вы пояснить, как должны выглядеть выходные данные для ваших образцов данных? Вы хотите, чтобы это было только для приглашенных команд или для домашних команд?