先初始化数据
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函数,与mysql的相同
分组之后从一个df变成group对象,里面是多个df
group对象再调用聚合函数,就是每个df用聚合函数得到一个结果,多个结果连成新df
df.groupby(["year"])
#
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
另一种是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"})
分组聚合就是上面的函数了,都是产生了另一个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)