pandas取组内最大值行
使用SQL的取法在随笔https://www.cnblogs.com/kang-mei-208/p/13845529.html中有提及
这里介绍pandas的取法
本文是实验楼课程数据分析与挖掘的练习题。友情推荐。
1.数据输入输出
数据输入用的是美国地震观测数据。
http://labfile.oss.aliyuncs.com/courses/1176/earthquake.csv
读入数据样例如下:
time | latitude | longitude | depth | mag | magType | nst | gap | dmin | rms | net | id | updated | place | type | horizontalError | depthError | magError | magNst | status | locationSource | magSource |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2018-09-19T02:42:05.360Z | 38.7765 | -122.729 | 1.47 | 0.72 | md | 6 | 150 | 0.008868 | 0.02 | nc | nc73087016 | 2018-09-19T02:43:41.278Z | 2km E of The Geysers, CA | earthquake | 0.67 | 0.61 | 0.14 | 2 | automatic | nc | nc |
2018-09-19T02:31:38.744Z | 66.385 | -157.328 | 5.5 | 1.3 | ml | 0.83 | ak | ak20258344 | 2018-09-19T02:36:28.347Z | 61km SSW of Kobuk, Alaska | earthquake | 0.3 | automatic | ak | ak | ||||||
2018-09-19T02:29:39.802Z | 62.3758 | -149.731 | 0 | 1.6 | ml | 0.72 | ak | ak20258342 | 2018-09-19T02:36:28.112Z | 20km ENE of Talkeetna, Alaska | earthquake | 0.4 | automatic | ak | ak | ||||||
2018-09-19T02:23:47.301Z | 60.4384 | -143.057 | 10.6 | 1 | ml | 0.28 | ak | ak20258340 | 2018-09-19T02:29:26.304Z | 54km NW of Cape Yakataga, Alaska | earthquake | 0.3 | automatic | ak | ak | ||||||
2018-09-19T02:16:19.050Z | 37.2318 | -114.941 | 7.9 | 0.7 | ml | 12 | 263.1 | 0.181 | 0.25 | nn | nn00657223 | 2018-09-19T02:17:34.122Z | 24km SE of Alamo, Nevada | earthquake | 22.4 | automatic | nn | nn | |||
2018-09-19T02:08:05.660Z | 33.65283 | -116.734 | 14.28 | 1.17 | ml | 41 | 58 | 0.06049 | 0.15 | ci | ci37359938 | 2018-09-19T02:18:38.670Z | 10km S of Idyllwild, CA | earthquake | 0.19 | 0.3 | 0.176 | 26 | automatic | ci | ci |
要求输出格式如下:
mag | region | times |
---|---|---|
micro | NV | 353 |
light | Nevada | 150 |
strong | CA | 31 |
major | Japan | 2 |
great | Indonesia | 1 |
其处理过程为:
- place字段的最后一个逗号后的地区构成region字段
- 将mag按以下规则映射:
震级 | 描述 |
---|---|
[0, 2) | micro |
[2, 5) | light |
[5, 7) | strong |
[7, 9) | major |
>=9 | great |
- 按照震级、地区聚合,算出各地区下各震级的发生次数
- 取出各个震级地震次数最多的地区
2.代码
# -*- coding: utf-8 -*-
"""
Created on Sun Jan 31 23:50:24 2021
@author: 25469
"""
import pandas as pd
def clean():
### 补充代码 ###
df_clean = None
df=pd.read_csv('earthquake.csv')
df1=pd.DataFrame({'time':df.time,'latitude':df.latitude,'longitude':df.longitude,'depth':df.depth,'mag':df.mag,'region':df.place.apply(lambda x:x.split(',')[-1])})
df1=df1.dropna().drop_duplicates()
df_clean=df1
return df_clean # 返回最终得到的 DataFrame
df=clean()
#映射
df['mag']=pd.cut(df.mag,bins=[0,2,5,7,9,20],labels=['micro','light','strong','major','great'])
#取出关键字段,聚合计数
df1=pd.DataFrame({'mag':df.mag,'region':df.region})
df1['times']=df1.groupby('region').transform('count') #构建聚合计数结果的times字段
df1.drop_duplicates(inplace=True) #这个聚合和SQL的还是有很大不同,类似开窗函数,需要手动删除重复项
#####得到各震级下最多次数的那行
#方法一
df_clean=df1.groupby('mag',as_index=False).apply(lambda x:x.sort_values(by='times').iloc[-1:]).reset_index(drop=True)
#方法二
df_clean=df1.sort_values(by='times',ascending=False).drop_duplicates('mag')
这里有两种方法:
- 用apply方法,将各个group排序后取出最后那行。
- 依照times排逆序,再以
mag
字段去重
这里推荐第一种方法。第二种方法有写些取巧,如果要取第二大的数字就不行了。
值得一提的是:
第一种方法的iloc[-1:]
这里,我如果只写iloc[-1]
,不加冒号,会报index错误
IndexError: single positional indexer is out-of-bounds
而加上冒号后却可以正常输出。他们的意思相同,都是取dataframe最后一行。
这种方法我参照的https://zhuanlan.zhihu.com/p/101284491?utm_source=wechat_session文章
奇怪的是,我输入文章中的数据集时,使用iloc[-1]
却不报错。
最终我也没能搞明白我的数据集最后一步iloc[-1]
为什么报错,好在加上冒号能够解决。
为了节省时间,我就不贴出来每一步操作结果的输出样例了,读者可以自行逐句看看输出,理解一下各个方法的输出。