[python]pandas数据分组相关

数据的分组

先初始化数据

import pandas as pd
import numpy as np
data = {'year':[2016,2016,2017,2017,2017,2018,2018,2019],
        'num':[2,5,4,7,8,90,78,5],
        'name':['a','b','c','d','e','f','g','h']}
df = pd.DataFrame(data)
groupby

分组使用groupby函数,与mysql的相同
分组之后从一个df变成group对象,里面是多个df
group对象再调用聚合函数,就是每个df用聚合函数得到一个结果,多个结果连成新df

df.groupby(["year"])
#<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f50644ee320>

df.groupby(["year"]).max() # 这里会导致分组使用的key变成idx,保持之前的表格加参数 as_index=False
#      num name
#year
#2016    5    b
#2017    8    e
#2018   90    g
#2019    5    h
df.groupby(["year"],as_index=False).max() # 这里取到的是2018组里num最大(90)和name最大(g),两者并不在一行
#   year  num name
#0  2016    5    b
#1  2017    8    e
#2  2018   90    g
#3  2019    5    h
agg

另一种是aggregate函数或者agg函数,对数据进行聚类操作
这个可以同时指定多种聚合函数

df.agg(["min","max"])
#     year  num name
#min  2016    2    a
#max  2019   90    h
# 还有一种使用字典指定名字的 我这个python3不支持了就不列出来了,只放个以前的例子
#df_c = df.groupby(["dept", "dest", "date", "class"])["book"].agg({"book_min":"min", "book_max":"max"})
merge

分组聚合就是上面的函数了,都是产生了另一个df,最后再合并到原本的df就是使用merge函数
与mysql的join一样理解,有left、right、inner等模式。

df_c = df.groupby(by=["year"])["num"].agg(["min","max"])
#      min  max
#year
#2016    2    5
#2017    4    8
#2018   78   90
#2019    5    5
df_c.columns = ["num_min", "num_max"] # 修改列名
df = pd.merge(df, df_c, how="left", on=["year"]) # 使用left join
df = pd.merge(df, df_c, how="left", left_on="year", right_on="year") # 也可以两边指定不同的列
#   year  num name  num_min  num_max
#0  2016    2    a        2        5
#1  2016    5    b        2        5
#2  2017    4    c        4        8
#3  2017    7    d        4        8
#4  2017    8    e        4        8
#5  2018   90    f       78       90
#6  2018   78    g       78       90
#7  2019    5    h        5        5

两个要注意的点,
1.merge的时候,最好保证两边的key在各自df里都不会重复,这样合并时候为一对一直接相连。如果有重复的话,会以笛卡尔积的方式增加行。
2.例如 left merge, 当有key左边有右边没有时,会以nan填充,左边没有右边有时候不会出现这一行。最后可以加dropna() 或者 fillna(0)来处理这种数据。

其他实用技巧
# 修改df的列顺序
cols = ["year", "num", "num_min", "num_max", "name"] # 设定新的顺序,只是修改了展示的顺序
df.loc[:, cols]
# 直接在df上修改
df.insert(7, "book", df.pop("book"))

# 分组将同一组的字符串相连
# 思路一 1.字符串变成数组 2.求该列sum 3.数组变字符串
# 还是粘个别的例子吧
#df["no"] = df["no"].apply(lambda x:[x])
#no = df.groupby(by=["dept", "dest", "date", "class", "depttime", "desttime"], as_index=False)["no"].sum()
#no["no"] = no["no"].apply(lambda x:"|".join(x))
# 
# 思路二 直接分组,然后apply一个函数每一组内该列的所有相连
df.groupby("year").apply(lambda x : "_".join([ a for a in x["name"] ]) )
# 说明:先分组,在apply一个函数,该函数是针对每一组(每个x)进行join操作,是把‘_’加入到当前组里name列的数组中
# 因为apply函数太慢踩过坑,不敢随便用了,期待大神路过指出更简便快捷的办法

# 取最大值所在的列
mask = df.groupby("year", as_index=False)["num"].idxmax() # idxmax是取最大值所在的index
df.iloc[mask] # 然后用iloc根据index取出相应的行

# 文件操作
df.to_csv("test", sep='\t', index=False, header=False) # 指定分隔符,行列的标签是否展示
df.read_csv("xx", sep='\t', index=False, header=False)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值