J'ai le dataframe suivant utilisant des pandas
df = pd.DataFrame({'Last_Name': ['Smith', None, 'Brown'],
'Date0': ['01/01/1999','01/06/1999','01/01/1979'], 'Age0': [29,44,21],
'Date1': ['08/01/1999','07/01/2014','01/01/2016'],'Age1': [35, 45, 47],
'Date2': [None,'01/06/2035','08/01/1979'],'Age2': [47, None, 74],
'Last_age': [47,45,74],
'Last_age_date': ['Error no date','07/01/2014','08/01/1979']})
Je voudrais ajouter une nouvelle colonne pour obtenir la date correspondant à la valeur présente dans 'Last_age' pour chaque ligne pour obtenir quelque chose comme ça:
df = pd.DataFrame({'Last_Name': ['Smith', None, 'Brown'],
'Date0': ['01/01/1999','01/06/1999','01/01/1979'], 'Age0': [29,44,21],
'Date1': ['08/01/1999','07/01/2014','01/01/2016'],'Age1': [35, 45, 47],
'Date2': [None,'01/06/2035','08/01/1979'],'Age2': [47, None, 74],
'Last_age': [47,45,74]})
3 Réponses :
Quelque chose comme ceci devrait faire ce que vous recherchez:
# get the age and column rows (you might have more than just the 2)
age_columns = [c for c in df.columns if 'Age' in c][::-1]
date_columns = [c for c in df.columns if 'Date' in c][::-1]
def get_last_age_date(row):
for age, date in zip(age_columns, date_columns):
if not np.isnan(row[age]):
return row[date]
return np.nan
# apply the function to all the rows in the dataframe
df['Last_age_date'] = df.apply(lambda row: get_last_age_date(row), axis=1)
# fix the NaN values to say 'Error no date'
df.Last_age_date.where(~df.Last_age_date.isna(), 'Error no date', inplace=True)
print(df)
Merci ça marche. Puis-je demander comment fonctionne la fonction? Je comprends que j'obtiens deux listes (une pour l'âge et une pour la date) que vous vérifiez si la valeur de la ligne [age] est nulle ou non et sinon vous obtenez la date. Mais je ne comprends pas comment vous obtenez la bonne date.
vous pouvez simplement obtenir les colonnes Date et Age en faisant df.filter (regex = 'Date | Age')
Désolé, je veux dire que je ne comprends pas comment vous obtenez la bonne date dans votre code. La fonction zip prend-elle les premiers éléments de chaque liste, puis le second et ainsi de suite?
Non. zip est un générateur très pratique qui trouve les éléments correspondants dans les listes adjacentes. Donc list1 = [1,2,3,4] et list2 = [a, b, c, d] puis zip (list1, list2) = [ (1, a), (2, b), (3, c), (4, d)] . La correspondance réelle se produit dans l'instruction if . Il dit, si je trouve un age et que la valeur n'est pas None, alors renvoie la date correspondante. Si je ne trouve rien (la dernière ligne de la fonction), retournez NaN.
Bienvenue dans Stackoverflow! Vous pouvez écrire une petite fonction et y parvenir. Votre trame de données d'entrée ressemble à ceci.
def last_Age(row):
if row['Last_age'] == row['Age2']:
return row['Date2']
elif row['Last_age'] == row['Age1']:
return row['Date1']
elif row['Last_age'] == row['Age0']:
return row['Date0']
df['Last_age_date']=df.apply(last_Age, axis = 1)
df
Last_Name Date0 Age0 Date1 Age1 Date2 Age2 Last_age Last_age_date
0 Smith 01/01/1999 29 08/01/1999 35 None 47.0 47 None
1 None 01/06/1999 44 07/01/2014 45 01/06/2035 NaN 45 07/01/2014
2 Brown 01/01/1979 21 01/01/2016 47 08/01/1979 74.0 74 08/01/1979
Écrivez une fonction comme celle-ci:
df
Last_Name Date0 Age0 Date1 Age1 Date2 Age2 Last_age
0 Smith 01/01/1999 29 08/01/1999 35 None 47.0 47
1 None 01/06/1999 44 07/01/2014 45 01/06/2035 NaN 45
2 Brown 01/01/1979 21 01/01/2016 47 08/01/1979 74.0 74
Je vais simplement utiliser wide_to_long pour remodeler votre df
s=pd.wide_to_long(df.reset_index(),['Date','Age'],i=['Last_age','index'],j='Drop') s.loc[s.Age==s.index.get_level_values(0),'Date'] Out[199]: Last_age index Drop 47 0 2 None 45 1 1 07/01/2014 74 2 2 08/01/1979 Name: Date, dtype: object df['Last_age_date']=s.loc[s.Age==s.index.get_level_values(0),'Date'].values df Out[201]: Last_Name Date0 Age0 ... Age2 Last_age Last_age_date 0 Smith 01/01/1999 29 ... 47.0 47 None 1 None 01/06/1999 44 ... NaN 45 07/01/2014 2 Brown 01/01/1979 21 ... 74.0 74 08/01/1979 [3 rows x 9 columns]
cela devrait être plus élevé car c'est la seule approche vectorisée parmi toutes les réponses
@JohnJohn regarde d'abord wide_to_long pandas.pydata.org/ pandas-docs / stable / reference / api /…