Как отфильтровать определенные значения в последовательных месяцах? - PullRequest
1 голос
/ 13 января 2020

У меня есть структура данных, структурированная следующим образом:

Name    Month Grade

Sue     Jan   D

Sue     Feb   D

Jason   Mar   B

Sue     Mar   D

Jason   Jan   B

Sue     Apr   A

Jason   Feb   C

Я хочу получить список студентов, которые получили D 3 месяца подряд за последние 6 месяцев. В приведенном выше примере Сью будет в списке, так как она получила D в январе, феврале и марте. Как я могу сделать это, используя Python или Pandas или Numpy?

Ответы [ 3 ]

0 голосов
/ 13 января 2020

у вас есть несколько способов справиться с этим, сначала воспользуйтесь моим предыдущим решением, но для этого потребуется отображение c чисел в месяцах (т. Е. Сентябрь = 1, август = 12), чтобы вы могли применять математику для последовательной работы значения.

ниже необходимо преобразовать Месяц в DateTime и вычислить разницу в месяцах, затем мы можем применить накопительную сумму и отфильтровать любые значения больше 3.

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)

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

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
0 голосов
/ 13 января 2020

Я придумал это.

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)

Вывод:

['Sue']
0 голосов
/ 13 января 2020

Я пытался решить вашу проблему. У меня есть решение для вас, но оно может быть не самым быстрым с точки зрения эффективности / выполнения кода. Пожалуйста, см. Ниже:

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)]

Вывод будет выглядеть следующим образом:

Month Jan Feb Mar Apr concatenated
Name                              
Sue     D   D   D   A         DDDA

Если вам нужны только имена, тогда вместо них следующая команда.

newdf[newdf['concatenated'].str.contains('DDD', regex=False, na=False)].index.to_list()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...