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

其处理过程为:

  1. place字段的最后一个逗号后的地区构成region字段
  2. 将mag按以下规则映射:
震级 描述
[0, 2) micro
[2, 5) light
[5, 7) strong
[7, 9) major
>=9 great
  1. 按照震级、地区聚合,算出各地区下各震级的发生次数
  2. 取出各个震级地震次数最多的地区

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]为什么报错,好在加上冒号能够解决。

为了节省时间,我就不贴出来每一步操作结果的输出样例了,读者可以自行逐句看看输出,理解一下各个方法的输出。

原文地址:https://www.cnblogs.com/kang-mei-208/p/14357695.html