#python #pandas
#python #pandas
Вопрос:
У меня есть фрейм данных следующим образом:
name country gender
wang ca 1
jay us 1
jay ca 0
jay ca 1
lisa en 0
lisa us 1
Я хочу назначить пол на основе кода ‘US’. Если имя такое же, то весь пол должен совпадать с полом, присвоенным code us. Для имени, которое не имеет дубликатов, мы возвращаем ту же строку.
Возвращаемый результат должен быть
name code gender
wang ca 1
jay us 1
lisa us 1
Я использовал
df.gropuby(['name', 'country'])['gender'].transform()
Есть предложения о том, как это исправить?
Комментарии:
1. есть ли только одна строка для каждого имени / страны? Если нет, то как вы хотите определить пол?
2. если «страна» — это США, и есть повторяющиеся имена, весь пол соответствует полу США. Если повторяющихся имен нет, строка остается.
Ответ №1:
# Get country and gender in separate lists for a name
a = df.groupby('name')['country'].apply(list).reset_index(name='country_list')
b = df.groupby('name')['gender'].apply(list).reset_index(name='gender_list')
# Merge
df2 = a.merge(b, on='name', how='left')
# Using apply get final required values
def get_val(x):
cl, gl = x
final = [cl[0], gl[0]]
for c,g in zip(cl,gl):
if c=='us':
final.append(c)
final.append(g)
return final
df2['final_col'] = df2[['country_list', 'gender_list']].apply(get_val, axis=1)
df2['code'] = df2['final_col'].apply(lambda l: l[0])
df2['gender'] = df2['final_col'].apply(lambda l: l[1])
print(df2)
Комментарии:
1. Я не sure…as ваша логика для вычисления
gender
не straightforward..so возможно, вам придется создать свою собственную, используяapply
функцию.
Ответ №2:
Подход, который я использовал, — это merge()
с последующей условной заменой ( np.where()
)
Это немного сложнее, но будет работать для условий, отличных от ваших выборочных данных.
import io
import numpy as np
df = pd.read_csv(io.StringIO("""name country gender
wang ca 1
jay us 1
jay ca 0
jay ca 1
lisa en 0
lisa us 1"""), sep="s ")
# use "us" as basis for lookup. left merge on name only
df2 = (df.merge(df.query("country=='us'"),
on=["name"], how="left", suffixes=("", "_new"))
# replace only where it's not "us" and "us" has a different value
.assign(gender=lambda x: np.where((x["country"]!="us")amp;
(x["gender"]!=x["gender_new"])amp;
~(x["gender_new"].isna())
# force type casting so it doesn't become float64 because of NaN
, x["gender_new"].fillna(-1).astype("int64"),
x["gender"]))
# remove columns inserted by merge...
.drop(columns=["country_new", "gender_new"])
)
вывод
name country gender
wang ca 1
jay us 1
jay ca 1
jay ca 1
lisa en 1
lisa us 1
Комментарии:
1. это однострочный… Я разделил на несколько строк для удобства чтения. отсутствие цикла плюс очень защитные условия, гарантирующие, что он всегда будет работать.