#python #pandas #apply
Вопрос:
Вот игрушечный пример фрейма данных my pandas:
country_market language_market
0 United States English
1 United States French
2 Not used Not used
3 Canada OR United States English
4 Germany English
5 United Kingdom French
6 United States German
7 United Kingdom English
8 United Kingdom English
9 Not used Not used
10 United States French
11 United States English
12 United Kingdom English
13 United States French
14 Not used English
15 Not used English
16 United States French
17 United States Not used
18 Not used English
19 United States German
Я хочу добавить столбец top_country
, который показывает, является ли значение в country_market
одной из двух наиболее часто встречающихся стран в данных. Если это так, я хочу, чтобы в новом top_country
столбце отображалось значение, country_market
а если нет, то я хочу, чтобы в нем отображалось «Другое». Я хочу повторить этот процесс для language_market
(и целого ряда других рыночных столбцов, которые я здесь не показываю).
Вот как я хотел бы, чтобы данные выглядели после обработки:
country_market language_market top_country top_language
0 United States English United States English
1 United States French United States French
2 Not used Not used Not used Other
3 Canada OR United States English Other English
4 Germany English Other English
5 United Kingdom French Other French
6 United States German United States Other
7 United Kingdom English Other English
8 United Kingdom English Other English
9 Not used Not used Not used Other
10 United States French United States French
11 United States English United States English
12 United Kingdom English Other English
13 United States French United States French
14 Not used English Not used English
15 Not used English Not used English
16 United States French United States French
17 United States Not used United States Other
18 Not used English Not used English
19 United States German United States Other
Я создал функцию original_top_markets_function
для этого, но я не мог понять, как передать value_counts
часть моей функции пандам apply
. Я продолжал получать AttributeError: 'str' object has no attribute 'value_counts'
.
def original_top_markets_function(x):
top2 = x.value_counts().nlargest(2).index
for i in x:
if i in top2:
return i
else:
return 'Other'
Я знаю, что это связано apply
с тем, что я рассматриваю каждый элемент в моем целевом столбце, но мне также нужна функция для рассмотрения всего столбца сразу, чтобы я мог использовать value_counts
. Я не знаю, как это сделать.
Поэтому я придумал эту top_markets
функцию в качестве решения, используя список, который делает то, что я хочу, но не очень эффективен. Мне нужно будет применить эту функцию ко множеству различных рыночных столбцов, поэтому я хотел бы что-то более питоническое.
def top_markets(x):
top2 = x.value_counts().nlargest(2).index
results = []
for i in x:
if i in top2:
results.append(i)
else:
results.append('Other')
return results
Вот воспроизводимый пример. Пожалуйста, не могли бы вы как-нибудь помочь мне исправить мою top_markets
функцию, чтобы я мог ее использовать apply
?
import pandas as pd
d = {0: {'country_market': 'United States', 'language_market': 'English'},
1: {'country_market': 'United States', 'language_market': 'French'},
2: {'country_market': 'Not used', 'language_market': 'Not used'},
3: {'country_market': 'Canada OR United States',
'language_market': 'English'},
4: {'country_market': 'Germany', 'language_market': 'English'},
5: {'country_market': 'United Kingdom', 'language_market': 'French'},
6: {'country_market': 'United States', 'language_market': 'German'},
7: {'country_market': 'United Kingdom', 'language_market': 'English'},
8: {'country_market': 'United Kingdom', 'language_market': 'English'},
9: {'country_market': 'Not used', 'language_market': 'Not used'},
10: {'country_market': 'United States', 'language_market': 'French'},
11: {'country_market': 'United States', 'language_market': 'English'},
12: {'country_market': 'United Kingdom', 'language_market': 'English'},
13: {'country_market': 'United States', 'language_market': 'French'},
14: {'country_market': 'Not used', 'language_market': 'English'},
15: {'country_market': 'Not used', 'language_market': 'English'},
16: {'country_market': 'United States', 'language_market': 'French'},
17: {'country_market': 'United States', 'language_market': 'Not used'},
18: {'country_market': 'Not used', 'language_market': 'English'},
19: {'country_market': 'United States', 'language_market': 'German'}}
df = pd.DataFrame.from_dict(d, orient='index')
def top_markets(x):
top2 = x.value_counts().nlargest(2).index
results = []
for i in x:
if i in top2:
results.append(i)
else:
results.append('Other')
return results
df['top_country'] = top_markets(df['country_market'])
df['top_language'] = top_markets(df['language_market'])
df
Ответ №1:
Если необходимо работать с несколькими столбцами DataFrame.apply
в какой-либо функции, например, здесь lambda function
используйте:
cols = ['language_market', 'country_market']
f = lambda x: np.where(x.isin(x.value_counts().nlargest(2).index), x, 'Other')
df = df.join(df[cols].apply(f).add_prefix('total_'))
Решение без лямбда-функции:
def top_markets(x):
return np.where(x.isin(x.value_counts().nlargest(2).index), x, 'Other')
df = df.join(df[cols].apply(top_markets).add_prefix('total_'))
Комментарии:
1. Идеально, делает то, что мне нужно, и я могу легко использовать это для 30 столбцов, которые мне нужно преобразовать таким образом, спасибо!
Ответ №2:
Я думаю, что вы можете просто использовать:
df['top_country'] = np.where(df['country_market'].isin(df['country_market'].value_counts().nlargest(2).index), df['country_market'], 'Other')
df['top_language'] = np.where(df['language_market'].isin(df['language_market'].value_counts().nlargest(2).index), df['language_market'], 'Other')
Если вы хотите использовать свою собственную функцию, вы можете использовать:
df['top_country'] = df[['country_market']].apply(top_markets)
df['top_language'] = df[['language_market']].apply(top_markets)
#OR
df[['top_country', 'top_language']] = df[['country_market', 'language_market']].apply(top_markets)
Редактировать в соответствии с обсуждением в комментариях:
def top_markets(x, top):
if x in top:
return x
else:
'Other'
top_country = df['country_market'].value_counts().nlargest(2).index
top_languages = df['language_market'].value_counts().nlargest(2).index
df['top_country'] = df['country_market'].apply(lambda x: top_markets(x, top_country))
df['top_language'] = df['language_market'].apply(lambda x: top_markets(x, top_languages))
Комментарии:
1. Отлично, это действительно дает мне то, что я ищу! Но, в более общем плане, есть ли способ использовать функцию
value_counts
как часть функции, которую я хочу передатьapply
?2. Я думаю, что это более быстрый способ сделать это, чем использование пользовательской функции
3. Да, я не возражаю против скорости
np.where
, но для моего собственного обучения я хотел бы знать, как использовать что-то вродеvalue_counts
функции, к которой я перехожуapply
.4. @meenaparam — проверьте другой ответ.
5. Проверьте отредактированный ответ, если вы хотите использовать пользовательскую функцию