Вот пример моего фрейма данных:
df = pd.DataFrame([['Arsenal FC', '', ''],
['In', 'Age', 'Nat.'],
['Leandro Trossard', 28, 'Belgium'],
['Jakub Kiwior', 22, 'Poland'],
['Jorginho', 32, 'Italy'],
['Chelsea FC', '', ''],
['In', 'Age', 'Nat.'],
['Enzo Fernández ', 22, 'Argentina'],
['Mykhaylo Mudryk', 22, 'Ukraine'],
], columns=['Player', 'Age', 'Nat.'])
Я хочу создать новый столбец "Club"
, который принимает строковое значение ячейки в "Player"
и прикрепляет его к игроку ниже.
Сложность заключается в том, чтобы правильно clubs
назначить правильно players
Это мой желаемый результат:
df = pd.DataFrame([['In', 'Age', 'Nat.'],
['Leandro Trossard', 28, 'Belgium', 'Arsenal FC'],
['Jakub Kiwior', 22, 'Poland', 'Arsenal FC'],
['Jorginho', 32, 'Italy', 'Arsenal FC'],
['In', 'Age', 'Nat.'],
['Enzo Fernández ', 22, 'Argentina', 'Chelsea FC'],
['Mykhaylo Mudryk', 22, 'Ukraine', 'Chelsea FC'],
], columns=['Player', 'Age', 'Nat.', 'Club'])
Я не могу найти другой вопрос, который относится к этой проблеме. Возможно ли это в питоне?
Один из вариантов использования логических масок с mask и ffill:
# which rows are empty string on Age?
m1 = df['Age'].ne('')
# which row are not internal headers?
m2 = df['Player'].ne('Player')
out = df[m1&m2].assign(Club=df.loc[m2, 'Player'].mask(m1).ffill())
Выход:
Player Age Nat. Club
2 Leandro Trossard 28 Belgium Arsenal FC
3 Jakub Kiwior 22 Poland Arsenal FC
4 Jorginho 32 Italy Arsenal FC
7 Enzo Fernández 22 Argentina Chelsea FC
8 Mykhaylo Mudryk 22 Ukraine Chelsea FC
Промежуточные продукты:
Player m1 mask ffill
0 Arsenal FC False Arsenal FC Arsenal FC
2 Leandro Trossard True NaN Arsenal FC
3 Jakub Kiwior True NaN Arsenal FC
4 Jorginho True NaN Arsenal FC
5 Chelsea FC False Chelsea FC Chelsea FC
7 Enzo Fernández True NaN Chelsea FC
8 Mykhaylo Mudryk True NaN Chelsea FC
# which rows are empty string on Age?
m1 = df['Age'].ne('')
# which row are not internal headers?
m2 = df['Player'].ne('In')
out = df[m1].assign(Club=df.loc[m2, 'Player'].mask(m1).ffill())
Выход:
Player Age Nat. Club
1 In Age Nat. NaN
2 Leandro Trossard 28 Belgium Arsenal FC
3 Jakub Kiwior 22 Poland Arsenal FC
4 Jorginho 32 Italy Arsenal FC
6 In Age Nat. NaN
7 Enzo Fernández 22 Argentina Chelsea FC
8 Mykhaylo Mudryk 22 Ukraine Chelsea FC
@code_machine вы, наверное, сами догадались, что теперь вам нужно использовать m2 = df['Player'].ne('In')
, аналогично, если у вас есть NaN вместо пустых строк, вы можете заменить ne('')
на notna()
;)
Спасибо! Есть ли способ использовать этот метод, не удаляя столбцы ['In', 'Age', 'Nat.']
?
Привет @mozway, возможно ли добиться того, о чем я упоминал в комментарии выше? Метод 6c00h работает хорошо, но требует создания списка из 60+ названий клубов.
@code_machine да конечно, нужно просто удалить &m2
, смотрите обновление
Отредактировано:
df = pd.DataFrame([['Arsenal FC', '', ''],
['In', 'Age', 'Nat.'],
['Leandro Trossard', 28, 'Belgium'],
['Jakub Kiwior', 22, 'Poland'],
['Jorginho', 32, 'Italy'],
['Chelsea FC', '', ''],
['In', 'Age', 'Nat.'],
['Enzo Fernández ', 22, 'Argentina'],
['Mykhaylo Mudryk', 22, 'Ukraine'],
], columns=['Player', 'Age', 'Nat.'])
clubs = []
current_club = None
for i, row in df.iterrows():
if row['Player'] in ['Arsenal FC', 'Chelsea FC']:
current_club = row['Player']
elif row['Player'] == 'In':
continue
else:
clubs.append(current_club)
df['Club'] = clubs
print(df)
Выход:
Player Age Nat. Club
0 Arsenal FC Arsenal FC
1 In Age Nat. NaN
2 Leandro Trossard 28 Belgium Arsenal FC
3 Jakub Kiwior 22 Poland Arsenal FC
4 Jorginho 32 Italy Arsenal FC
5 Chelsea FC Chelsea FC
6 In Age Nat. NaN
7 Enzo Fernández 22 Argentina Chelsea FC
8 Mykhaylo Mudryk 22 Ukraine Chelsea FC
Редактировать 2: Несколько названий клубов
clubs = ['Arsenal FC', 'Chelsea FC', 'Other Club 1', 'Other Club 2', ..., 'Other Club n']
def get_club(row, clubs):
if row['Player'] in clubs:
return row['Player']
else:
return ''
df['Club'] = ''
club = ''
for index, row in df.iterrows():
if row['Player'] in clubs:
club = row['Player']
else:
df.at[index, 'Club'] = club
df = df[df['Club'] != ''].reset_index(drop=True)
df['Club'] = df.apply(lambda x: get_club(x, clubs), axis=1)
Всем привет! Можно ли использовать этот метод, не удаляя столбцы ['In', 'Age', 'Nat.']
?
Большое спасибо. Есть ли другой способ реализовать этот код, когда существует несколько названий клубов (60+), кроме «Арсенал» и «Челси»?
Вы можете расширить код для обработки нескольких названий клубов, создав список всех названий клубов и сверив столбец Player с этим списком.
Привет @mozway! Это не работает для меня прямо сейчас, но я отредактировал вопрос, чтобы отразить мой фактический фрейм данных.