Группировка по уникальному имени и статусу с последней датой - PullRequest
5 голосов
/ 28 марта 2019

Я хотел бы проанализировать статистику по автомобилям, которые ремонтировались, а какие были новыми.Пример выборки:

Name   IsItNew    ControlDate
Car1    True      31/01/2018
Car2    True      28/02/2018
Car1    False     15/03/2018
Car2    True      16/04/2018
Car3    True      30/04/2018
Car2    False     25/05/2018
Car1    False     30/05/2018    

Итак, я должен groupby по Имени, и если есть столбец False в IsItNew, я должен установить False и первую дату, когда Falseбыло.

Я пытался groupby с nunique():

df = df.groupby(['Name','IsItNew', 'ControlDate' ])['Name'].nunique()

Но он возвращает количество уникальных предметов в каждой группе.

Как я могу получитьтолько сгруппированные уникальные предметы без подсчета?

Actual result is:

Name   IsItNew       ControlDate
Car1    True         31/01/2018     1
        False        15/03/2018     1
                     30/05/2018     1
Car2    True         28/02/2018     1
                     16/04/2018     1
        False        25/05/2018     1 
Car3    True         30/04/2018     1


Expected Result is:

Name   IsItNew     ControlDate
Car1    False      15/03/2018
Car2    False      25/05/2018
Car3    True       30/04/2018

Буду признателен за любую идею.Спасибо)

Ответы [ 2 ]

2 голосов
/ 28 марта 2019

Один из способов сделать это - GroupBy Name и объединить в IsItNew с двумя функциями. Пользовательский, использующий any для проверки наличия каких-либо значений False и idxmin для поиска индекса первого False, который впоследствии можно использовать для индексации кадра данных на ControlDate:

df_ = df.groupby('Name').agg({'IsItNew':
                                   {'IsItNew':lambda x: ~(~x).any(),
                                    'ControlDate':'idxmin'}})
                        .droplevel(0, axis=1)
                        .reset_index()

df_['ControlDate'] = df.loc[df_['ControlDate'].values, 'ControlDate'].reset_index(drop=True)

  xName  IsItNew ControlDate
0  Car1    False  15/03/2018
1  Car2    False  25/05/2018
2  Car3     True  30/04/2018
1 голос
/ 28 марта 2019

Сначала преобразовать столбец в дату и время по to_datetime, затем отсортировать по 3 столбцам с DataFrame.sort_values и последним получить первую строку по столбцу Name s по DataFrame.drop_duplicates:

df['ControlDate'] = pd.to_datetime(df['ControlDate'])

df = df.sort_values(['Name','IsItNew', 'ControlDate']).drop_duplicates('Name')

print (df)
   Name  IsItNew ControlDate
2  Car1    False  2018-03-15
5  Car2    False  2018-05-25
4  Car3     True  2018-04-30

РЕДАКТИРОВАТЬ:

print (df)
   Name  IsItNew ControlDate
0  Car1     True  31/01/2018
1  Car2     True  28/02/2018
2  Car1    False  15/03/2018
3  Car2     True  16/04/2018
4  Car3     True  30/04/2018
5  Car2    False  25/05/2018
6  Car1    False  30/05/2018
7  Car3     True  20/10/2019
8  Car3     True  30/04/2017

#set to datetimes
df['ControlDate'] = pd.to_datetime(df['ControlDate'])
#sorting by 3 columns
df1 = df.sort_values(['Name','IsItNew', 'ControlDate'])

#create Series for replace
s = df1.drop_duplicates('Name', keep='last').set_index('Name')['ControlDate']

#filter by Falses
df2 = df1.drop_duplicates('Name').copy()
#replace True rows by last timestamp
df2.loc[df2['IsItNew'], 'ControlDate'] = df2.loc[df2['IsItNew'], 'Name'].map(s)
print (df2)
   Name  IsItNew ControlDate
2  Car1    False  2018-03-15
5  Car2    False  2018-05-25
8  Car3     True  2019-10-20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...