2
votes

Comment faire une sélection complexe chez les pandas?

J'ai un df comme ci-dessous:

timestamp   President
1992-01-01  B Clinton
1992-01-02  B Clinton
...
2000-01-01  G Bush
...

Je veux créer un autre df, quelque chose comme ça

President   Start Date  End Date
B Clinton   1992-01-01  1999-12-31
G Bush      2000-01-01  2007-12-31
B Obama     2008-01-01  2015-12-31
D Trump     2016-01-01  2019-12-31 # not too far away!!

En gros, je veux créer une trame de données dont son index est horodaté, puis son contenu est sélectionné en fonction de la condition des deux colonnes d'un autre df.

Je pense qu'il y a un moyen au sein des pandas de le faire, mais je ne le suis pas sûr comment. J'ai essayé d'utiliser np.piecewise mais il semble que générer les conditions sera très difficile pour moi. Comment pourrais-je faire cela?


0 commentaires

3 Réponses :


2
votes

Vous pouvez utiliser pd.date_range pour créer une plage de dates à partir des valeurs de début et de fin. Assurez-vous que les dates de début et de fin sont au format datetime.

s = df.set_index('President').apply(lambda x: pd.Series(pd.date_range(x['Start Date'], x['End Date'])), axis = 1).stack().reset_index(1, drop = True)

new_df = pd.DataFrame(s.index.values, index=s, columns = ['President'] )



            President
1992-01-01  B Clinton
1992-01-02  B Clinton
1992-01-03  B Clinton
1992-01-04  B Clinton
1992-01-05  B Clinton
1992-01-06  B Clinton
1992-01-07  B Clinton
1992-01-08  B Clinton
1992-01-09  B Clinton


1 commentaires

Vous ne voudrez peut-être pas utiliser apply. :-) stackoverflow.com/questions/54432583/...



4
votes

Ceci est un autre problème de désemboîtement

def unnesting(df, explode):
    idx=df.index.repeat(df[explode[0]].str.len())
    df1=pd.concat([pd.DataFrame({x:np.concatenate(df[x].values)} )for x in explode],axis=1)
    df1.index=idx
    return df1.join(df.drop(explode,1),how='left')

Pour info, j'ai collé la fonction ici

df['New']=[pd.date_range(x,y).tolist() for x , y in zip (df.StartDate,df.EndDate)]

unnesting(df,['New'])


0 commentaires

0
votes

Vous pourriez peut-être utiliser un PeriodIndex au lieu d'un DatetimeIndex car vous avez affaire à des intervalles de temps régulièrement espacés, c'est-à-dire des années.

# create a list of PeriodIndex objects with annual frequency
p_idxs = [pd.period_range(start, end, freq='A') for idx, (start, end) in df[['Start Date', 'End Date']].iterrows()]

# for each PeriodIndex create a DataFrame where 
# the number of president instances matches the length of the PeriodIndex object
df_list = []
for pres, p_idx in zip(df['President'].tolist(), p_idxs):
    df_ = pd.DataFrame(data=len(p_idx)*[pres], index=p_idx)
    df_list.append(df_)

# concatenate everything to get the desired output
df_desired = pd.concat(df_list, axis=0)


0 commentaires