Pour ce DataFrame pandas (qui est en réalité beaucoup plus long), je voudrais obtenir la valeur de b et de la date, où b est le minimum et b est le maximum pour ce jour. Les performances sont un problème.
import datetime import pandas as pd df = pd.DataFrame({"a": ["29.12.1999 23:59:12", "29.12.1999 23:59:13", "29.12.1999 23:59:14", "30.12.1999 23:59:12", "30.12.1999 23:59:13", "30.12.1999 23:59:14", "31.12.1999 23:59:12", "31.12.1999 23:59:13", "31.12.1999 23:59:14"], "b": [1, 2, 3, 3, 1, 2, 2, 3, 1]}) df["date"] = pd.to_datetime(df.a) df.drop(["a"],axis=1,inplace=True)
Je voudrais donc obtenir
b date 0 1 1999-12-29 23:59:12 2 3 1999-12-29 23:59:14 3 3 1999-12-30 23:59:12 4 1 1999-12-30 23:59:13 7 3 1999-12-31 23:59:13 8 1 1999-12-31 23:59:14
Voici comment le dataframe est généré:
b date 0 1 1999-12-29 23:59:12 1 2 1999-12-29 23:59:13 2 3 1999-12-29 23:59:14 3 3 1999-12-30 23:59:12 4 1 1999-12-30 23:59:13 5 2 1999-12-30 23:59:14 6 2 1999-12-31 23:59:12 7 3 1999-12-31 23:59:13 8 1 1999-12-31 23:59:14
3 Réponses :
Commencez par convertir la date
en format de date, puis nous trions la valeur b
en utilisant sort_values
, et en utilisant drop_duplicates code > pour obtenir ce dont vous avez besoin
df=df.assign(days=df.date.dt.date).sort_values('b')
yourdf=pd.concat([df.drop_duplicates('days'),df.drop_duplicates('days',keep='last')]).\
sort_index().\
drop('days',1)
yourdf
Out[242]:
b date
0 1 1999-12-29 23:59:12
2 3 1999-12-29 23:59:14
3 3 1999-12-30 23:59:12
4 1 1999-12-30 23:59:13
7 3 1999-12-31 23:59:13
8 1 1999-12-31 23:59:14
Peut-être pas le plus performant en raison de l'itération des dates, mais:
df['true_date'] = df['date'].dt.date date_min_max = df.groupby('true_date')['b'].agg(['min','max']) result = pd.DataFrame(columns=['b','date']) for date, min_max_series in date_min_max.iterrows(): date_values = df[(df['true_date'] == date) & df['b'].isin(min_max_series)][['b','date']] result = result.append(date_values) Out[170]: b date 0 1 1999-12-29 23:59:12 2 3 1999-12-29 23:59:14 3 3 1999-12-30 23:59:12 4 1 1999-12-30 23:59:13 7 3 1999-12-31 23:59:13 8 1 1999-12-31 23:59:14
>>> dfg = df.set_index('date').groupby(pd.Grouper(freq='D')) >>> df['dailyMin'] = df['date'].isin(dfg.idxmin()['b']) >>> df['dailyMax'] = df['date'].isin(dfg.idxmax()['b']) >>> df[df[['dailyMin', 'dailyMax']].any(axis=1)] b date dailyMin dailyMax 0 1 1999-12-29 23:59:12 True False 2 3 1999-12-29 23:59:14 False True 3 3 1999-12-30 23:59:12 False True 4 1 1999-12-30 23:59:13 True False 7 3 1999-12-31 23:59:13 False True 8 1 1999-12-31 23:59:14 True False This might not be the most effective way to do this. I have my doubts about .isin(). Also this partially depends on your dataset---see this discussion: Select the max row per group - pandas performance issue
Et quel code ou quelles idées avez-vous proposé pour gérer ce problème?
Approche SQL: deux requêtes avec (order by) + (limit 1) si vous avez juste besoin du min et du max et rien d'autre. C'est bien mieux que de récupérer plus de 10 000 lignes pour obtenir 2 valeurs.