我想分析每辆汽车的统计数据,这些统计数据是修理的和新的。数据样本为:
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
任何想法,我将不胜感激。谢谢)
答案 0 :(得分:2)
一种实现方法是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 :(得分:1)
首先按to_datetime
将列转换为日期时间,然后按DataFrame.sort_values
按3列排序,最后按DataFrame.drop_duplicates
按列Name
s首先获取行:
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