J'ai un dataframe structuré comme suit:
Name Month Grade Sue Jan D Sue Feb D Jason Mar B Sue Mar D Jason Jan B Sue Apr A Jason Feb C
Je veux obtenir la liste des étudiants qui ont obtenu D 3 mois consécutifs au cours des 6 derniers mois. Dans l'exemple ci-dessus, Sue sera sur la liste depuis qu'elle a obtenu D en janvier, février et mars. Comment puis-je faire cela en utilisant Python ou Pandas ou Numpy?
3 Réponses :
J'ai essayé de résoudre votre problème. J'ai une solution pour vous mais ce n'est peut-être pas la plus rapide en termes d'efficacité / exécution de code. Veuillez voir ci-dessous:
newdf[newdf['concatenated'].str.contains('DDD', regex=False, na=False)].index.to_list()
La sortie sera comme:
Month Jan Feb Mar Apr concatenated Name Sue D D D A DDDA
Si vous voulez juste les noms, alors la commande suivante à la place. p>
newdf = df.pivot(index='Name', columns='Month', values='Grade')
newdf = newdf[['Jan', 'Feb', 'Mar', 'Apr']].fillna(-1)
newdf['concatenated'] = newdf['Jan'].astype('str') + newdf['Feb'].astype('str') + newdf['Mar'].astype('str') + newdf['Apr'].astype('str')
newdf[newdf['concatenated'].str.contains('DDD', regex=False, na=False)]
Approche intéressante, cela fonctionne définitivement et ouvre même des perspectives plus intéressantes. Le dernier morceau de code ne fonctionnait cependant pas lorsque vous filtrez le DDD dans la colonne concaténée. Au lieu de cela, je reset_index et filtre la colonne.
vous avez plusieurs façons de gérer cela, utilisez d'abord ma solution précédente, mais cela nécessitera de mapper les nombres académiques sur les mois (par exemple, septembre = 1, août = 12) de cette façon, vous pouvez appliquer les mathématiques pour calculer des valeurs consécutives. p> ce qui suit consiste à convertir le mois en date-heure et à calculer la différence en mois, nous pouvons ensuite appliquer une somme cumulative et filtrer toutes les valeurs supérieures à 3.
print(df.loc[df['Name'] == 'Sue']) Name Month Grade date count 3 Sue Dec D 1899-12-01 1 0 Sue Jan D 1900-01-01 2 1 Sue Feb D 1900-02-01 3 5 Sue Apr A 1900-04-01 1
print(df.drop('date',axis=1))
Name Month Grade count
4 Jason Jan B 1
6 Jason Feb C 1
2 Jason Mar B 1
3 Sue Dec D 1
0 Sue Jan D 2
1 Sue Feb D 3
5 Sue Apr A 1
d = StringIO("""Name Month Grade
Sue Jan D
Sue Feb D
Jason Mar B
Sue Dec D
Jason Jan B
Sue Apr A
Jason Feb C""")
df = pd.read_csv(d,sep='\s+')
df['date'] = pd.to_datetime(df['Month'],format='%b').dt.normalize()
# set any values greater than June to the previous year.
df['date'] = np.where(df['date'].dt.month > 6,
(df['date'] - pd.DateOffset(years=1)),df['date'])
df.sort_values(['Name','date'],inplace=True)
def month_diff(date):
cumlative_months = (
np.round(((date.sub(date.shift(1)) / np.timedelta64(1, "M")))).eq(1).cumsum()
) + 1
return cumlative_months
df['count'] = df.groupby(["Name", "Grade"])["date"].apply(month_diff)
J'ai trouvé ceci.
['Sue']
Résultat:
df['Month_Nr'] = pd.to_datetime(df.Month, format='%b').dt.month
names = df.Name.unique()
students = np.array([])
for name in names:
filter = df[(df.Name==name) & (df.Grade=='D')].sort_values('Month_Nr')
if filter['Month_Nr'].diff().cumsum().max() >= 2:
students = np.append(students, name)
print(students)
Les données sont-elles triées temporairement?
Avez-vous supposé qu'il y avait la même année?
@mephisto Non. Tant qu'il est consécutif, il peut s'agir d'années différentes. Par exemple, Jason devrait être sur la liste s'il a obtenu D en novembre 2018, décembre 2018 et janvier 2019.
votre mois est-il exactement tel qu'il est ici ou une date appropriée? comme le
15 janvier 2018ou le15/1/2019@ansev Qu'entendez-vous par temporairement? Autant que je sache, il n'y a pas de tri spécial sur les données.
La colonne de date @Datanovice est telle qu'elle est présentée ici.
L'ordre des données d'entrée implique-t-il l'ordre du mois? Par exemple, si j'ai la note de Sue avec janvier, février, ..., décembre en 2018 et janvier, février en 2019, le deuxième Sue Jan implique-t-il toujours l'année suivante?
@Shenan Je filtre depuis 6 mois dans l'ensemble de données. Il n'y aura donc pas de valeurs de 2 janvier. Cependant, il peut y avoir des valeurs du 18 novembre, du 18 décembre et du 19 janvier. Par exemple, Jason devrait être sur la liste s'il obtient D en novembre 2018, décembre 2018 et janvier 2019
@Eenes check solution, cela devrait gérer les données sur plusieurs années.