pandas分组找某字段max的记录transform、top2 nlargest、除数+1避免除0异常、pd.to_timedelta(int, unit='D')、相同条件筛选赋值、NaN关系运算False、pandas时间处理

昨天睡太晚,上午状态不好,一边完善昨日的小结,一边在打瞌睡,中午去吃了个饭,没办法睡觉,下午状态也不好,下午继续撸代码,其实效率有点慢啊,我订的两个比赛的review是一个周40个小时完成,但是目前一个比赛已经花了2个工作日review,而且后面还有很多,但是收获也有很多。反正自己把几点该做的做好,如果一天尽力了确实只能完成这么多那也只能慢慢来!尽力没尽力一个看专注程度,具体实施起来很好办,那就是不开社交软件,把手机扣在一边。然后另外一个很重要的就是前一天一定要休息好,还有中午休息好,这样效率才高得上去!

下面对今天的工作做一些总结

对于昨天的算差分的时候用shift方法,我尝试了diff()方法是完全可行的。

研究了分组按某字段取最大记录的pandas实现方法,方法应该说有两种:
第一种很高效就是用transform,比如uid分组按时间取最大一条记录,df.groupby('uid')['time'].transform(max),transform的效果是不改变df的行数,每一行是按组的该组最大值,在组内这个值是相等的,所以直接做个比较df.groupby('uid')['time'].transform(max) == df['time']就得到一个mask,然后用这个mask去筛选就好,df[mask]

第二种方法比较低效,原理都是类似的,只是要进入到每一个分组中去做比较和筛选,相当于就是用apply去进行循环
gb = df.groupby('uid')
gb_selected = gb.apply(lambda x : x[x['time'] == x['time'].max()])
这里gb_selected是产生了一个多重索引第一层是uid,第二层是本身df的索引
把他drop掉就可以了
gb_result = gb_selected.reset_index(drop=True)
这种方式效率比较慢

取分组最大的2个df.groupby('uid')['time'].nlargest(2),相应的还有smallest,这里有一个地方需要注意啊,df.groupby('uid')['time'].nlargest(2)会形成多重索引,第一层是uid,第二层是原本df的index,可以把第二层索引筛出来,用于找到这些分组top2的行,方法是top2_indexs = df.groupby('uid')['time'].nlargest(2).index.get_level_values(1),多重index,每一层叫做一个level,0层1层,然后df.loc[top2_indexs]就可以了

然后做除法的时候可以+1避免除0异常,但是我想这个1的数量相对于变量本身应该很小才比较好

如何在series的层级进行datetime+timedelta的操作?原本作者使用的是apply进行操作,
t_loan.apply(lambda x: x["loan_time"] + timedelta(days=x["plannum"] * 30), axis=1)
这里注意,这是df的apply函数,所以可以作用于column,也可以作用于row,
axis=1就是作用于每行,axis=0作用于每列。

但是我觉得可以不用以apply的方式,可以直接在Series层级进行操作:
df_loan['loan_time'] + pd.to_timedelta(df_loan['plannum'] * 30,unit='D')
这里的关键就是pd.to_timedelta,就产生一个timedelta64[ns]的dtype,所以可以直接和datetime64[ns]进行加运算

接下来是一个updateLimit的函数,实际上就是两个Series的比较,如果S1 < S2的部分,把S2赋值给S1即可,作者又写绕了,用了一个冗余的筛选,然后又apply到每一行进行if操作,这里仍然可以用更高层级的写法直接就是一个条件筛选:
duser.loc[duser['limit']<duser['new_limit'],'limit'] = duser.loc[duser['limit']<duser['new_limit'],'new_limit']
两边都加上条件即可,也就是把满足这个关系的行找出来,把new_limit赋值给limit即可

NaN和任意数关系运算结果都是False

pd.Timestamp感觉就是对datetime.datetime的封装
pd.Timedelta感觉就是对datetime.timedelta的封装
所以datetime.timedelta的方法,pd.Timedelta也有
然后如果对于Series要进行pd.Timestamp级别的操作,只需要Series.dt.XXX就可以






留言

熱門文章