import pandas as pd
Series是一种类似于一维数组的对象,由标签(行索引)和数据组成。
方法:pd.Series(),传入不同的对象即可;默认索引从0开始。
xxxxxxxxxxs1 = pd.Series(["a","b","c","d"])s10 a1 b2 c3 ddtype: object
xxxxxxxxxxs2 = pd.Series(["a","b","c","d"],index=[1,2,3,4])s21 a2 b3 c4 ddtype: object
字典key:value,key是索引,value是数据
xxxxxxxxxxs3 = pd.Series({"a":1,"b":2,"c":3,"d":4})s3a 1b 2c 3d 4dtype: int64
xxxxxxxxxxs2 = pd.Series(["a","b","c","d"],index=[1,2,3,4])s2.indexInt64Index([1, 2, 3, 4], dtype='int64')
xxxxxxxxxxs1 = pd.Series(["a","b","c","d"])s1.valuesarray(['a', 'b', 'c', 'd'], dtype=object)
Series是由一组数据与一组行索引组成的数据结构。
DataFrame是由一组数据与一对索引(行索引、列索引)组成的表格型数据结构。
行、列索引默认是从0开始的。
xxxxxxxxxxdf1 = pd.DataFrame(['a', 'b', 'c', 'd'])df100 a1 b2 c3 d
xdf2 = pd.DataFrame([["a","A"], ["b","B"], ["c","C"], ["d","D"]])df20 10 a A1 b B2 c C3 d D
设置columns参数指定列索引;设置index参数指定行索引。
xxxxxxxxxx# 设置列索引df3 = pd.DataFrame([["a","A"], ["b","B"], ["c","C"], ["d","D"]],columns=["小写","大写"])df3小写 大写0 a A1 b B2 c C3 d D
xxxxxxxxxx# 设置行索引df4 = pd.DataFrame([["a","A"], ["b","B"], ["c","C"], ["d","D"]],index=[1,2,3,4])df40 11 a A2 b B3 c C4 d D
xxxxxxxxxx# 行、列索引同时设置df34 = pd.DataFrame([["a","A"], ["b","B"], ["c","C"], ["d","D"]],columns=["小写","大写"],index=[1,2,3,4])df34小写 大写1 a A2 b B3 c C4 d D
字典的key就是列索引,value就是一列数据。
xxxxxxxxxxdata = {"小写":['a', 'b', 'c', 'd'],"大写":['A', 'B', 'C', 'D']}df5 = pd.DataFrame(data)df5小写 大写0 a A1 b B2 c C3 d D
xxxxxxxxxx# 列索引df34.cloumnsIndex(['小写', '大写'], dtype='object')# 行索引df34.indexInt64Index([1, 2, 3, 4], dtype='int64')
主要用到的是read_XXX()方法,XXX表示导入文件的格式。
pandas默认的行数、列数都是从0开始计数,0,1,2,3,......
电脑文件路径默认使用\时,前面加上一个r避免被转义。
xxxxxxxxxx# 路径前面加上rdf = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx")# 路径前面不加rdf = pd.read_excel("C:/User/XXX/Desktop/test.xlsx")df = pd.read_excel("C:\\User\\XXX\\Desktop\\test.xlsx")
xxxxxxxxxxdf = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx",sheet_name = "Sheets1")df = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx",sheet_name = 2)
xxxxxxxxxxdf = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx",sheet_name = "Sheets1",index_col = 0) # 第1列作为行索引
xxxxxxxxxx# 第2行为列索引df = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx",sheet_name = "Sheets1",header = 1)
xxxxxxxxxx# 指定一列df = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx",usecols = 1)# 指定多列df = pd.read_excel(r"C:\User\XXX\Desktop\test.xlsx",usecols = [1,3,5])
xxxxxxxxxxdf = pd.read_csv(r"C:\User\XXX\Desktop\test.csv")
csv文件数据默认以逗号(,)分开。
xxxxxxxxxxdf = pd.read_csv(r"C:\User\XXX\Desktop\test.csv", sep = ";")
参数nrows表示读取前面几行。
xxxxxxxxxxdf = pd.read_csv(r"C:\User\XXX\Desktop\test.csv", nrows = 3)
常见的两种编码格式:UTF-8 和 GBK,默认格式UTF-8
xxxxxxxxxxdf = pd.read_csv(r"C:\User\XXX\Desktop\test.csv", encoding = "utf-8") # 默认编码格式,可省略df = pd.read_csv(r"C:\User\XXX\Desktop\test.csv", encoding = "gbk")
当文件路径或者文件名包包含中文时,如果导入报错,就需要设置engine参数;当调用read_csv()方法时,默认使用C语文作为解释器,所以把C更改为Python就可以了。
xxxxxxxxxxdf = pd.read_csv(r"C:\User\XXX\Desktop\test.csv", engine = "python")
xxxxxxxxxxdf = pd.read_table(r"C:\User\XXX\Desktop\test.txt", sep = ",") # txt文件df = pd.read_table(r"C:\User\XXX\Desktop\test.csv", sep = ",") # csv文件
xxxxxxxxxximport pymysql# 创建连接eng = pymysql.connect(host='localhost',user='user',password='passwd',db='db',charset='utf8')pd.read_sql(sql,con)# 参数sql表示执行的sql语句;参数con是创建好的数据连接,即eng
使用head()方法,括号中输入行数,默认展示前5行。
xxxxxxxxxxdf.head() # 默认展示前5行数据df.head(3) # 展示前3行数据姓名 性别 年龄 注册时间工号1001 张三 女 18 2022-04-161002 李四 女 46 2022-04-271003 王五 男 54 2022-04-08
xxxxxxxxxxdf.shape(3,4) # 表示df表有3行,4列
xxxxxxxxxxdf.info()<class 'pandas.core.frame.DataFrame'>Int64Index: 4 entries, 1001 to 1004Data columns (total 4 columns):姓名 4 non-null object性别 4 non-null object年龄 4 non-null int64注册时间 4 non-null datetime64[ns]dtypes: datetime64[ns](1), int64(1), object(2)memory usage: 160.0+ bytes
最小值min、最大值max、标准差std、均值mean、数量统计count
xxxxxxxxxxdf.describe()年龄count 4.00000mean 38.75000std 15.47848min 18.0000025% 32.2500050% 41.5000075% 48.00000max 54.00000
缺失值一般用NaN表示。
性别这列非null是3,其它列都是4,这说明性别这一列有1个null值。
xxxxxxxxxxdf.info()<class 'pandas.core.frame.DataFrame'>RangeIndex: 4 entries, 0 to 3Data columns (total 5 columns):工号 4 non-null object姓名 4 non-null object性别 3 non-null object年龄 4 non-null int64注册时间 4 non-null datetime64[ns]dtypes: datetime64[ns](1), int64(1), object(3)memory usage: 288.0+ bytes
判断是否有缺失值,如果有缺失值则返回True,否则返回False。
xxxxxxxxxx工号 姓名 性别 年龄 注册时间0 A001 张三 女 18 2022-04-161 A002 李四 女 46 2022-04-272 A003 王五 NaN 54 2022-04-083 A004 显均学苑 男 37 2022-04-19
xxxxxxxxxxdf.isnull()工号 姓名 性别 年龄 注册时间0 False False False False False1 False False False False False2 False False True False False3 False False False False False
用fillna()方法进行填充缺失值。
xxxxxxxxxxdf.fillna(0) # 缺省值填充0
使用字典指明列(key)和填充值(value)
xxxxxxxxxxdf.fillna({"性别":"男","年龄":0}) # 分别对性别和年龄进行填充
duplicated():判断是否有重复值
drop_duplicates() :删除重复值
xxxxxxxxxx工号 姓名 性别 年龄 注册时间0 A001 张三 女 18 2022-04-161 A002 李四 女 18 2022-04-272 A003 王五 男 54 2022-04-083 A003 显均学苑 男 37 2022-04-194 A003 王五 男 54 2022-04-085 A001 张三 女 18 2022-04-166 A001 张三 女 18 2022-04-16
参数与drop_duplicates()一样。
xxxxxxxxxxdf.duplicated()0 False1 False2 False3 False4 True5 True6 Truedtype: bool
默认对每行所有值(是否有相同的行)进行重复值判断,并且只保留第1个(行)值。
针对一列或多列时,使用subset参数设置;如果是多列(指定的几列行相同),就用列表传入。
参数keep设置重复值的保留方式,注意加上引号("")
默认first(第一个);也可以last(最后一个);也可以False(重复值全部删除).
xxxxxxxxxxdf.drop_duplicates() # 对所有字段重复值(删除相同行保留第一行)df.drop_duplicates(subset="工号") # 对工号列df.drop_duplicates(subset=["工号","注册日期"]) # 多列时传入列表df.drop_duplicates(subset="工号", keep = "last") # 保留最后一个,注意引号("")df.drop_duplicates(subset="工号", keep = False) # 不保留重复值(全部删除)
| 类型 | 说明 |
|---|---|
| int | 整数 |
| float | 浮点数,即包含有小数的数 |
| object | Python对象,用O表示 |
| string_ | 字符串,用S表示。S10表示长度为10的字符串 |
| unicode_ | 固定长度的unicode类型,与字符串定义方式一样 |
| datetime64[ns] | 时间格式 |
info() 查看所有列
dtype 查看某一列
xxxxxxxxxxdf["工号"].dtype # 查看工号这一列的数据类型dtype('O') # 其它列dtype('int64')、dtype('<M8[ns]')
用astype()方法,括号里面指明转换的目标类型即可。
xxxxxxxxxxdf["年龄"].dtype("float32")
如果没有索引,默认0开始的整数做索引。df的columns参数传入列索引值;index参数传入行索引值。
xxxxxxxxxxdf.columns = ["工号", "姓名", "性别", "年龄"] # 列索引df.index = [1,2,3,4] # 行索引
xxxxxxxxxx# 生成了新表dfNew = df.set_index("工号")# 在原数据表上进行修改df.set_index("工号", inplace=True) # 设置将工号作为行索引,inplace=True在原数据表上修改# 保留df.set_index(“date”, drop=False)
xxxxxxxxxx# 生成了新表dfNew = df.rename(columns={"工号": "新工号","姓名":"新姓名"}) # 修改列索引名称# 在原数据表上进行修改df.rename(columns={"工号": "新工号","姓名":"新姓名"},inplace=True)df.rename(index={1:"a",2:"b",3:"c"}) # 修改行索引名称df.rename(columns={"工号": "新工号"},index={1:"a"}) # 同时修改列索引和行索引
主要用在层次化索引表中,用reset_index()方法,常用参数:level、drop、inplace
xxxxxxxxxx姓名 成交时间ID 编号101 A1 张三 2022-04-04102 A2 李四 2022-04-05103 A3 王五 2022-04-06104 A4 赵四 2022-04-07105 A5 显均学苑 2022-04-08
xxxxxxxxxxdf2 = df.reset_index() # 默认将全部index转化为columns,(全部索引转成列)print(df2)ID 编号 姓名 成交时间0 101 A1 张三 2022-04-041 102 A2 李四 2022-04-052 103 A3 王五 2022-04-063 104 A4 赵四 2022-04-074 105 A5 显均学苑 2022-04-08
xxxxxxxxxxdf3=df.reset_index(level=0, drop=False) # 默认drop=Falseprint(df3)ID 姓名 成交时间编号A1 101 张三 2022-04-04A2 102 李四 2022-04-05A3 103 王五 2022-04-06A4 104 赵四 2022-04-07A5 105 显均学苑 2022-04-08
xxxxxxxxxxdf4=df.reset_index(level=0,drop=True) # 指定0级索引将被删除,并不生成新列,即删除ID索引print(df4)姓名 成交时间编号A1 张三 2022-04-04A2 李四 2022-04-05A3 王五 2022-04-06A4 赵四 2022-04-07A5 显均学苑 2022-04-08
xxxxxxxxxx编号 姓名 ID 成交时间0 A1 张三 101 2022-04-041 A2 李四 102 2022-04-052 A3 王五 103 2022-04-063 A4 赵四 104 2022-04-074 A5 显均学苑 105 2022-04-08
总结:(1)当列参数用数字时 iloc ;当列参数用文本时 loc 。
(2)数字可以是一个区间,取多列,例如 [0:2],默认左闭右开。
df[ ]方式(普通索引)
如果多个列名,则要用二维列表。用二维列表,可生成列索引。
xxxxxxxxxxdf["姓名"] # 一列0 张三1 李四2 王五3 赵四4 显均学苑Name: 姓名, dtype: object
xxxxxxxxxxdf[["姓名"]] # 一列姓名0 张三1 李四2 王五3 赵四4 显均学苑
xxxxxxxxxxdf[["ID","姓名"]] # 多列ID 姓名0 101 张三1 102 李四2 103 王五3 104 赵四4 105 显均学苑
iloc方法(位置索引)
xxxxxxxxxxdf.iloc[:,2] # 第3列0 1011 1022 1033 1044 105Name: ID, dtype: int64
xxxxxxxxxxdf.iloc[:, [0,2]] # 第1列和第3列编号 ID0 A1 1011 A2 1022 A3 1033 A4 1044 A5 105
xxxxxxxxxxdf.iloc[:, 0:2]] # 获取第1-2列,不包含第3列编号 姓名0 A1 张三1 A2 李四2 A3 王五3 A4 赵四4 A5 显均学苑
冒号(:)不输入数字,表示所有的行,方括号表示获取的列位置,从0开始。
0:2表示选择第1至2列,不包含第3列。
loc(普通索引),行索引标签(名称)
xxxxxxxxxxdf.loc["一"]df.loc[["一", "二", "三"]]
iloc方法(位置索引),行索引号,从0开始
选择一行、几行、连续行
xxxxxxxxxxdf.iloc[0] # 第1行编号 A1姓名 张三ID 101成交时间 2022-04-04 00:00:00Name: 0, dtype: object
xxxxxxxxxxdf.iloc[[0]] # 第1行编号 姓名 ID 成交时间0 A1 张三 101 2022-04-04
xxxxxxxxxxdf.iloc[[0,2]] # 第1行、第3行编号 姓名 ID 成交时间0 A1 张三 101 2022-04-042 A3 王五 103 2022-04-06
xxxxxxxxxxdf.iloc[0:2] # 第1-2行编号 姓名 ID 成交时间0 A1 张三 101 2022-04-041 A2 李四 102 2022-04-05
布尔索引 选择满足条件的行
xxxxxxxxxxdf[df["ID"]>103] # ID号大于103的行编号 姓名 ID 成交时间3 A4 赵四 104 2022-04-074 A5 显均学苑 105 2022-04-08
xxxxxxxxxxdf[(df["ID"]>103) & (df["姓名"]=="赵四")] # 多个条件编号 姓名 ID 成交时间3 A4 赵四 104 2022-04-07
是指行和列相交的部分。
普通索引 + 普通索引
xxxxxxxxxxdf.loc[["a","c"],["工号","姓名"]]
位置索引 + 位置索引
xxxxxxxxxxdf.iloc[[0,1],[0,2]]
布尔索引 + 普通索引
xxxxxxxxxxdf[df[”年龄“]<50][["工号","姓名"]]
切片索引 + 切片索引
xxxxxxxxxxdf.iloc[[1:3],[0:2]]
切片索引 + 普通索引
xxxxxxxxxxdf.ix[0:3,["工号","姓名"]]
replace(A,B) 表示将A替换成B。
xxxxxxxxxx# 姓名这一列进行替换df["姓名"].replace("张三","新张三",inplace=True) # 原表上张三替换成新张三# 整个表上进行替换,相当于fillna()方法df.replace(np.NaN,0)
replace([A,B],C)表示将A、B替换成C。
xxxxxxxxxxdf33["姓名"].replace(["张三","李四"],"新张三",inplace=True)
replace({"A":"a","B","b"})表示将A替换成a ,B替换成b
xxxxxxxxxxdf.replace({"张三":"新张三","李四":"新李四"},inplace=True)
sort_values()方法,by指明要排序的列名,ascending表示升序(默认)还是降序排列;默认为True升序。
xxxxxxxxxx# 按照ID升序排列df.sort_values(by="ID")# 按照ID降序排列df.sort_values(by="ID",ascending=False)
以列表形式指明要排序的多列列名、每列的排序方式。
xxxxxxxxxxdf.sort_values(by=["ID","年龄"],ascending=[True,False])
当有缺失值时,na_position参数对显示位置进行设置,默认值为last,表示将缺失值显示在最后;first表示将缺失值显示在前面。
xxxxxxxxxxdf.sort_values(by="ID",na_position="first")
rank()方法主要有两个参数,ascending指明升序(默认)还是降序;method表示待排列值有重复值时的处理方法。
averge 重复值的平均排名
first 重复值出现的先后顺序
min 重复值对应的最小排名
max 重复值对应的最大排名
xxxxxxxxxxdf["ID"]0 1011 1022 1033 1024 105Name: ID, dtype: float64
重复值102分别占第2和第3名,平均值为2.5
xxxxxxxxxxdf["ID"].rank(method="average")0 1.01 2.52 4.03 2.54 5.0
xxxxxxxxxxdf["ID"].rank(method="first") # 先后顺序0 1.01 2.02 4.03 3.04 5.0
xxxxxxxxxxdf["ID"].rank(method="min") # 最小值0 1.01 2.02 4.03 2.04 5.0
xxxxxxxxxxdf["ID"].rank(method="max") # 最大值0 1.01 3.02 4.03 3.04 5.0
xxxxxxxxxx编号 姓名 ID 成交时间0 A1 张三 101 2022-04-041 A2 李四 102 2022-04-052 A3 王五 103 2022-04-063 A4 赵四 102 2022-04-074 A5 显均学苑 105 2022-04-08
drop()方法,指明删除的列名或者列的位置(第几列);
xxxxxxxxxxdf.drop(["ID","编号"],axis=1) # 加参数axis=1df.drop(columns=["ID","编号"]) # 不加参数axis=1df.drop(df33.columns[[0,2]],axis=1) # 加参数axis=1
drop()方法,与删除列类似,指出删除的行名或行的位置;
xxxxxxxxxxdf.drop([1,4],axis=0)df.drop(index=[1,4])df.drop(df.index[[2,4]],axis=0)
我们不能直接删除满足条件的值,而是把不满足条件值筛选出来作为新的数据源,这样就把要删除的行过滤掉了。
例如:要删除ID大于103的行,则把ID小于103的行筛选出来作为新的数据源。
xxxxxxxxxxdf[df["ID"]<103]0 A1 张三 101 2022-04-041 A2 李四 102 2022-04-053 A4 赵四 102 2022-04-07
value_counts()方法,对某些值出现的次数进行计数。
xxxxxxxxxx# 统计次数df["ID"].value_counts()102 2103 1101 1105 1# 统计占比情况df["ID"].value_counts(normalize=True)102 0.4103 0.2101 0.2105 0.2df["ID"].value_counts(normalize=True,sort=False)105 0.2101 0.2102 0.4103 0.2
unique()方法,获取某一列的唯一值。
xxxxxxxxxxdf["ID"].unique()array([101, 102, 103, 105], dtype=int64)
isin()方法,某列中是否包含某个值或多个值,多个值时用列表。如果包含返回True,否则返回False
xxxxxxxxxxdf["ID"].isin([102,103])0 False1 True2 True3 True4 False
例如:(0,3] 即 0< X ≤ 3 ,表示大于0,小于等于3
xxxxxxxxxx# 切分成指定的区间pd.cut(df["ID"],bins=[100,102,105])0 (100, 102]1 (100, 102]2 (102, 105]3 (100, 102]4 (102, 105]
xxxxxxxxxx# 切分成3个区间pd.qcut(df["ID"],3)0 (100.999, 102.0]1 (100.999, 102.0]2 (102.667, 105.0]3 (100.999, 102.0]4 (102.667, 105.0]
pandas中没有专门插入行的方法;可以把待插入的行当作新表,然后两个表在纵轴方向进行拼接。
插入新的列的方法如下:
insert()方法,指明插入位置、新列的列名、新列的数据。
xxxxxxxxxxdf.insert(2,"年龄",[45,50,36,28,22])编号 姓名 年龄 ID 成交时间0 A1 张三 45 101 2022-04-041 A2 李四 50 102 2022-04-052 A3 王五 36 103 2022-04-063 A4 赵四 28 102 2022-04-074 A5 显均学苑 22 105 2022-04-08
直接以索引方式进行列插入,新列在最后的位置。
xxxxxxxxxxdf["年龄"] = [45,50,36,28,22]编号 姓名 ID 成交时间 年龄0 A1 张三 101 2022-04-04 451 A2 李四 102 2022-04-05 502 A3 王五 103 2022-04-06 363 A4 赵四 102 2022-04-07 284 A5 显均学苑 105 2022-04-08 22
行列互换(又称转置),就是将行数据转换到列方向上,将列数据转换到行方向上。
xxxxxxxxxxdf.T # 注意没有括号0 1 2 3 4编号 A1 A2 A3 A4 A5姓名 张三 李四 王五 赵四 显均学苑ID 101 102 103 102 105成交时间 2022-04-04 2022-04-05 2022-04-06 2022-04-07 2022-04-08
索引重塑就是将原来的索引重新构造。
xxxxxxxxxxdf=pd.DataFrame([[1,2,3],[4,5,6]],columns=["C1","C2","C3"],index=["S1","S2"])dfC1 C2 C3S1 1 2 3S2 4 5 6# 树形数据df.stack()S1 C1 1C2 2C3 3S2 C1 4C2 5C3 6# 表格型数据df.stack().unstack()C1 C2 C3S1 1 2 3S2 4 5 6
前提条件是需要公共列。
id_vars 转换时保持不变的列;
var_name 原宽表中除了id_vars中列名外的列名,重新命名为一个新的列名(写入原表中所在的列名称);
value_name 原宽表中除了id_vars中列外的数据,重新命名为一个新的列名(写入数据)。
xxxxxxxxxxdf=pd.DataFrame([["A","B",1,2,3],["C","D",4,5,6]],columns=["C1","C2","C3","C4","C5"])dfC1 C2 C3 C4 C50 A B 1 2 31 C D 4 5 6# 宽表转成长表dfnew=df.melt(id_vars=["C1","C2"],var_name="列名C3-5",value_name="数值")dfnewC1 C2 列C3-5 数值0 A B C3 11 C D C3 42 A B C4 23 C D C4 54 A B C5 35 C D C5 6
将长表转换成宽表就是宽表转长表的逆过程,常用的方法是数据透视表。
xxxxxxxxxxdfnew.pivot_table(index=["C1","C2"],columns="列名C3-5",values="数值")列名C3-5 C3 C4 C5C1 C2A B 1 2 3C D 4 5 6
在DateFrame中与map()函数类似的有两个,一个是apply()函数,另一个是applymap()函数,需要与匿名函数lambda结合使用。
xxxxxxxxxx# 源数据表dfdfC1 C2 C3S1 1 2 3S2 4 5 6S3 7 8 9# apply()函数,对C1列中每一个元素加1df["C1"].apply(lambda x:x+1)S1 2S2 5S3 8# applymap()函数,对df表中每一个元素加1dfnew=df.applymap(lambda x:x+1)dfnewC1 C2 C3S1 2 3 4S2 5 6 7S3 8 9 10# 对源数据表C1列每一个元素加1,并修改源表df["C1"]=df["C1"].apply(lambda x:x+1)dfC1 C2 C3S1 2 2 3S2 5 5 6S3 8 8 9
算术运算就是基本的加、减、乘、除运算,是对应元素进行加、减、乘、除运算。
xxxxxxxxxxdfC1 C2 C3S1 1 2 3S2 4 5 6df["C1"]+df["C2"]S1 3S2 9df["C1"]-df["C2"]df["C1"]*df["C2"]df["C1"]/df["C2"]
常规的大于、等于、小于之类的运算,只是在列与列之间进行比较。
xxxxxxxxxxdfC1 C2 C3S1 1 2 3S2 4 5 6df["C1"]>df["C2"]S1 FalseS2 False
算术和比较运算都是在列与列之间进行的,有多少行的值就会返回多少个结果,而汇总运算是将数据进行汇总返回一个汇总以后的结果值。
默认计算每一列的非空数值的个数。可设置axis=1,计算每一行的非空数值的个数。
xxxxxxxxxxdfC1 C2 C3S1 1 2 3S2 4 5 6# 每一列df.count()C1 2C2 2C3 2# 每一行df.count(axis=1)S1 3S2 3# 只计算一列df["C1"].count()2
默认对每一列进行求和;可设置axis=1,对每一行进行求和。
xxxxxxxxxxdfC1 C2 C3S1 1 2 3S2 4 5 6# 每一列df.sum()C1 5C2 7C3 9# 每一行df.sum(axis=1)S1 6S2 15# 只计算C1列df["C1"].sum()5
默认对每一列进行求均值运算;可设置axis=1,对每一行进行求均值。在Excel中是average()函数。
xxxxxxxxxxdfC1 C2 C3S1 1 2 3S2 4 5 6# 每一列df.mean()C1 2.5C2 3.0C3 4.0# 每一行df.mean(axis=1)S1 2S2 5# 只计算C1列df["C1"].mean()2.5
默认计算每一列最大值,若axis=1,则计算每一行最大值。
xxxxxxxxxx# 每一列df.max()# 每一行df.max(axis=1)
默认计算每一列最小值,若axis=1,则计算每一行最小值。
xxxxxxxxxx# 每一列df.min()# 每一行df.min(axis=1)
xxxxxxxxxx# 每一列df.median()# 每一行df.median(axis=1)
xxxxxxxxxxdf.quantile(0.25) # 每一列df.quantile(0.25, axis=1) # 每一行
相关性常用来衡量两个事物之间的相关程度。相关性计算就是计算相关系数,比较常见的皮尔逊相关系数corr()。
xxxxxxxxxx# C1和C2相关系数df["C1"].corr(df["c2"])# 整个DataFrame表中各列两两之间的相关性df.corr()C1 C2 C3C1 1.0 1.0 1.0C2 1.0 1.0 1.0C3 1.0 1.0 1.0
xxxxxxxxxxfrom datetime import datetimedatetime.now() # 当前日期和时间datetime.datetime(2022, 4, 22, 22, 6, 54, 478590)datetime.now().year # 年datetime.now().month # 月datetime.now().day # 日datetime.now().weekday()+1 # 周几,周一到周日(0~6),所以加1datetime.now().isocalender()(2022, 16, 5) # 2022年第16周的第5天datetime.now().isocalender()[1] # 返回周数1616datetime.now().date() # 日期datetime.datetime(2022, 4, 22)datetime.now().time() # 时间datetime.datetime(22, 6, 54, 478590)
使用strtime()函数自定义时间和日期的格式。
H 24小时制,I 12小时制,M 两位数的分 ,S 秒
w 星期几,从0开始,U每年的第几周,周日是每周第1天 ,W每年的第几周,周一是每周第1天
xxxxxxxxxxdatetime.now().strftime("%Y-%m-%d")2022-04-22datetime.now().strftime("%Y-%m-%d %H:%M:%S")2022-04-22 22:39:43
xxxxxxxxxxfrom dateutil.parser import parsestr_date = "2022-4-22"parse(str_date)
选取某一时间或者某一时间段内对应的值。
xxxxxxxxxxindex = pd.DatetimeIndex(["2022-04-1","2022-04-2","2022-04-3","2022-04-4","2022-04-5","2022-04-6","2022-04-7","2022-04-8","2022-04-9"])data = pd.DataFrame(np.arange(1,10),columns=["num"],index=index)print(data)num2022-04-01 12022-04-02 22022-04-03 32022-04-04 42022-04-05 52022-04-06 62022-04-07 72022-04-08 82022-04-09 9
xxxxxxxxxxdata["2022"] # 获取2022年的数据data["2022-01"] # 获取2022年4月的数据data["2022-04-03":"2022-04-05"] # 获取2022-04-01到2022-04-05的数据num2022-04-03 32022-04-04 42022-04-05 5
上面的方法只适用于索引是时间的情况下。如果时间在普通列,那么利用布尔索引对非索引列进行比较来选取。
xxxxxxxxxxdf[df["成交时间"]==datetime(2022,4,22)] # 成交时间为2022-04-22的订单df[df["成交时间"]>datetime(2022,4,22)] # 成交时间在2022-04-22之后的订单# 成交时间在2022-04-5~15之间的订单df[(df["成交时间"]>datetime(2022,4,5)) & (df["成交时间"]<datetime(2022,4,15))]
计算两个时间之差会返回一个timedelta对象,该对象中包含天数、秒、微秒,如果要获取小时、分钟,则需要进行计算。
xxxxxxxxxxd = datetime(2022,4,22,10,20,30)- datetime(2022,4,20,20,30,40)ddatetime.timedelta(days=1, seconds=49790) # 返回值d.days # 相差的天数1d.secounds # 相差的秒数49790d.secounds/3600 # 换算成小时13.83
时间往前或往后推移一段时间,即加减一段时间。有两种方式实现时间偏移:
使用timedelta只能偏移天、秒、微秒单位的时间,如果其它单位的时间运算,则需要换算成以上三种单位之一才能进行偏移。
xxxxxxxxxxfrom datetime import timedelta# 往后一天datetime(2022,4,22) + timedelta(days=1)# 往前10秒datetime(2022,4,22) - timedelta(seconds=10)
使用Pandas中的日期偏移量(date offset),可以实现按天、时、分、秒单位的时间偏移。
xxxxxxxxxxfrom pandas.tseries.offsets import Day,Hour,Minute,Secondd = datetime(2022,4,23,1,25,30)d = d + Day(1) # 加1天d = d + Hour(1) # 加1小时d = d + Minute(10) # 加10分钟d = d + Second(15) # 加15秒dTimestamp('2022-04-23 01:25:45')
利用groupby()方法
xxxxxxxxxx用户ID 客户分类 区域 是否省会 7月销量 8月销量 9月销量0 63784 A类 一线城市 是 1 1 11 46787 B类 三线城市 否 2 2 22 79933 C类 一线城市 是 3 3 33 74092 A类 二线城市 否 4 4 44 30391 B类 一线城市 否 5 5 55 32550 C类 二线城市 是 6 6 66 67517 A类 三线城市 是 7 7 77 34312 B类 二线城市 否 8 8 88 79359 C类 一线城市 否 9 9 9
运行groupby()返回的不是一个DataFrame对象,而是一个DataFrameGroupBy对象,需要对这些分组数据进行汇总计算 以后才会显示出来。
分组后对数据进行汇总运算的操作称为聚合,使用的函数称为聚合函数。
常用聚合函数:count、sum、mean、size、max、min、peak、std
xxxxxxxxxxdf.groupby("客户分类").count()用户ID 区域 是否省会 7月销量 8月销量 9月销量客户分类A类 3 3 3 3 3 3B类 3 3 3 3 3 3C类 3 3 3 3 3 3
xxxxxxxxxxdf.groupby("客户分类").sum()用户ID 7月销量 8月销量 9月销量客户分类A类 205393 12 12 12B类 111490 15 15 15C类 191842 18 18 18
xxxxxxxxxxdf.groupby(["客户分类","区域"]).count()用户ID 是否省会 7月销量 8月销量 9月销量客户分类 区域A类 一线城市 1 1 1 1 1三线城市 1 1 1 1 1二线城市 1 1 1 1 1B类 一线城市 1 1 1 1 1三线城市 1 1 1 1 1二线城市 1 1 1 1 1C类 一线城市 2 2 2 2 2二线城市 1 1 1 1 1
xxxxxxxxxxdf.groupby(["客户分类","区域"]).sum()用户ID 7月销量 8月销量 9月销量客户分类 区域A类 一线城市 63784 1 1 1三线城市 67517 7 7 7二线城市 74092 4 4 4B类 一线城市 30391 5 5 5三线城市 46787 2 2 2二线城市 34312 8 8 8C类 一线城市 159292 12 12 12二线城市 32550 6 6 6
无论分组键是一列还是多列,都是对所有可计算列进行计算。如果只想要其中一列或几列,可以通过列索引取出。
xxxxxxxxxxdf.groupby("客户分类")["用户ID","区域"].count()用户ID 区域客户分类A类 3 3B类 3 3C类 3 3
将DataFrame中一列取出来就是一个Series,例如df["客户分类"]
分组键是列名与分组键是Series,计算结果都一样,根本没有区别。
xxxxxxxxxxdf.groupby("客户分类").count()df.groupby(df["客户分类"]).count()df.groupby(["客户分类","区域"]).count()df.groupby([df["客户分类"],df["区域"]]).count()
前面用到的聚合函数都是直接在DataFrameGroupBy对象上调用,这样分组以后,所有列都是同一种汇总运算,且一次只能使用一种汇总方式。aggregate可以一次使用多种汇总方式。
在Pandas中,agg和aggregate两个函数指向同一个方法,使用时写任意一个即可。
xxxxxxxxxxdf.groupby("客户分类")["7月销量","8月销量","9月销量"].aggregate(["count","sum"])7月销量 8月销量 9月销量count sum count sum count sum客户分类A类 3 12 3 12 3 12B类 3 15 3 15 3 15C类 3 18 3 18 3 18
xxxxxxxxxxdf.groupby("客户分类").aggregate({"用户ID":"count","7月销量":"count","8月销量":"sum"})用户ID 7月销量 8月销量客户分类A类 3 3 12B类 3 3 15C类 3 3 18
agg调用 自定义函数
xxxxxxxxxx# 调用lambda函数df["7月销量"].agg(lambda x:x+1)# 调用自定义函数def fun_add(x)return x+1df["7月销量"].agg(fun_add(x))
agg 调用numpy的统计指标
xxxxxxxxxxdf["7月销量"].agg(np.sum)df["7月销量"].agg(np.sum,axis=1) # 以行方向相加
reset_index()方法
xxxxxxxxxxdf.groupby("客户分类").count().reset_index()客户分类 用户ID 区域 是否省会 7月销量 8月销量 9月销量0 A类 3 3 3 3 3 31 B类 3 3 3 3 3 32 C类 3 3 3 3 3 3
数据分组是在一维(行)方向上进行拆分,而数据透视表是在行、列方向上同时拆分。
pivot_table()方法
xxxxxxxxxxpivot_table(data, values=None, index=None, columns=None,aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
参数解释:其中有4个最重要的参数index、values、columns、aggfunc
在所有参数中,values、index、columns最为关键,它们分别对应excel透视表中的值、行、列。
最后补充两个函数
xxxxxxxxxxpd.pivot_table(df,values="用户ID",columns="区域",index="客户分类",aggfunc="count")区域 一线城市 三线城市 二线城市客户分类A类 1.0 1.0 1.0B类 1.0 1.0 1.0C类 2.0 NaN 1.0
xxxxxxxxxxpd.pivot_table(df,values="用户ID",columns="区域",index="客户分类",aggfunc="count",margins="True",margins_name="合计")区域 一线城市 三线城市 二线城市 合计客户分类A类 1.0 1.0 1.0 3B类 1.0 1.0 1.0 3C类 2.0 NaN 1.0 3合计 4.0 2.0 3.0 9
aggfunc传入列表或字典
xxxxxxxxxxpd.pivot_table(df,values=["用户ID","7月销量"],columns="区域",index="客户分类",aggfunc={"用户ID":"count","7月销量":"sum"},fill_value=0)7月销量 用户ID区域 一线城市 三线城市 二线城市 一线城市 三线城市 二线城市客户分类A类 1 7 4 1 1 1B类 5 2 8 1 1 1C类 12 0 6 2 0 1
xxxxxxxxxxpd.pivot_table(df,values=["用户ID","7月销量"],columns="区域",index="客户分类",aggfunc=["count","sum"],fill_value=0)count sum \7月销量 用户ID 7月销量区域 一线城市 三线城市 二线城市 一线城市 三线城市 二线城市 一线城市客户分类A类 1 1 1 1 1 1 1B类 1 1 1 1 1 1 5C类 2 0 1 2 0 1 12用户ID区域 三线城市 二线城市 一线城市 三线城市 二线城市客户分类A类 7 4 63784 67517 74092B类 2 8 30391 46787 34312C类 0 6 159292 0 32550
重置索引
xxxxxxxxxxpd.pivot_table(df,values="用户ID",columns="区域",index="客户分类",aggfunc="count").reset_index()区域 客户分类 一线城市 三线城市 二线城市0 A类 1.0 1.0 1.01 B类 1.0 1.0 1.02 C类 2.0 NaN 1.0
横向拼接是根据公共列在横向上进行两个表的拼接,主要利用merge()方法
就是两表的公共列是一对一的
xxxxxxxxxxdf1名次 姓名 学号 成绩0 1 张三 1001 801 2 王五 1002 852 3 李四 1003 903 4 赵四 1004 95df2学号 班级0 1001 一班1 1002 一班2 1003 二班3 1004 三班pd.merge(df1,df2)名次 姓名 学号 成绩 班级0 1 张三 1001 80 一班1 2 王五 1002 85 一班2 3 李四 1003 90 二班3 4 赵四 1004 95 三班
两表公共列不是一对一的,其中一个表的公共列有重复值,另一个表的公共列是唯一的。
xxxxxxxxxxdf1姓名 学号 数学0 张三 1001 801 王五 1002 852 李四 1003 90df2学号 语文0 1001 801 1002 852 1003 903 1001 954 1002 100pd.merge(df1,df2)姓名 学号 数学 语文0 张三 1001 80 801 张三 1001 80 952 王五 1002 85 853 王五 1002 85 1004 李四 1003 90 90
两表的公共列不是一对一的,且两表中的公共列都有重复值,多对多相当于多个多对一连接。
xxxxxxxxxxdf1姓名 学号 数学0 张三 1001 801 张三 1001 902 王五 1002 753 王五 1002 854 李四 1003 90df2学号 语文0 1001 801 1002 852 1003 903 1001 954 1002 100pd.merge(df1,df2)姓名 学号 数学 语文0 张三 1001 80 801 张三 1001 80 952 张三 1001 90 803 张三 1001 90 954 王五 1002 75 855 王五 1002 75 1006 王五 1002 85 857 王五 1002 85 1008 李四 1003 90 90
xxxxxxxxxxpd.merge(df1,df2)
xxxxxxxxxxpd.merge(df1,df2)pd.merge(df1,df2,on="学号")
xxxxxxxxxxdf1姓名 学号 语文0 张三 1001 801 李四 1002 852 王五 1003 90df2姓名 学号 数学0 张三 1001 801 李四 1002 852 王五 1003 90pd.merge(df1,df2,on=["姓名","学号"])姓名 学号 语文 数学0 张三 1001 80 801 李四 1002 85 852 王五 1003 90 90
当两个表中没有公共列,即列名称不同(实际值是一样的),分别指定左、右表连接键的列名,参数分别是left_on、right_on。
xxxxxxxxxxdf1姓名 学号 数学0 张三 1001 801 李四 1002 852 王五 1003 90df2班级 编号 语文0 一班 1001 801 二班 1002 852 三班 1003 90pd.merge(df1,df2,left_on="学号",right_on="编号")姓名 学号 数学 班级 编号 语文0 张三 1001 80 一班 1001 801 李四 1002 85 二班 1002 852 王五 1003 90 三班 1003 90
索引列不算是真正的列,当公共列是索引列时,就要把索引当作连接键,分别是left_index、right_index
xxxxxxxxxxdf1姓名 数学学号1001 张三 801002 李四 851003 王五 90df2班级 语文编号1001 一班 801002 二班 851003 三班 90pd.merge(df1,df2,left_index=True,right_index=True)姓名 数学 班级 语文学号1001 张三 80 一班 801002 李四 85 二班 851003 王五 90 三班 90
前面例子是比较标准的表,左表中的公共列的值可以在右表对应的公共列找到,右表公共列的值也可以在左表对应的公共列中找到,但现实业务中很多是互相找不到的,这时候用参数how来指明具体的连接方式。
xxxxxxxxxxdf1姓名 学号 数学0 张三 1001 801 李四 1002 852 王五 1003 90df2姓名 学号 语文0 张三 1001 801 李四 1004 852 王五 1003 90
取两个表的公共部分。
xxxxxxxxxxpd.merge(df1,df2,on="学号")pd.merge(df1,df2,on="学号",how="inner")姓名_x 学号 数学 姓名_y 语文0 张三 1001 80 张三 801 王五 1003 90 王五 90
以左表为基础,右表往左表上拼接,没有的值用NaN填充。
xxxxxxxxxxpd.merge(df1,df2,on="学号",how="left")姓名_x 学号 数学 姓名_y 语文0 张三 1001 80 张三 80.01 李四 1002 85 NaN NaN2 王五 1003 90 王五 90.0
以右表为基础,左表往右表上拼接,没有的值用NaN填充。
xxxxxxxxxxpd.merge(df1,df2,on="学号",how="right")姓名_x 学号 数学 姓名_y 语文0 张三 1001 80.0 张三 801 王五 1003 90.0 王五 902 NaN 1004 NaN 李四 85
取两个表的并集。
xxxxxxxxxxpd.merge(df1,df2,on="学号",how="outer")姓名_x 学号 数学 姓名_y 语文0 张三 1001 80.0 张三 80.01 李四 1002 85.0 NaN NaN2 王五 1003 90.0 王五 90.03 NaN 1004 NaN 李四 85.0
_x、_y、_z_myL”,"_myR"]xxxxxxxxxxpd.merge(df1,df2,on="学号",how="inner",suffixes=["_L","_R"])姓名_L 学号 数学 姓名_R 语文0 张三 1001 80 张三 801 王五 1003 90 王五 90
横向拼接是两个表根据公共列在水平方向上进行拼接,而纵向拼接是在垂直方向进行拼接,利用concat()方法。
xxxxxxxxxxdf1姓名 学号 语文0 张三 1001 801 李四 1002 852 王五 1003 90df2姓名 学号 语文0 张三 1001 801 赵四 1004 852 王五 1003 90
xxxxxxxxxxpd.concat([df1,df2])姓名 学号 语文0 张三 1001 801 李四 1002 852 王五 1003 900 张三 1001 801 赵四 1004 852 王五 1003 90
pd.concat()默认保留原表的索引,如果生成新的索引(不保留原表索引)使用参数 ignore_index=True
xxxxxxxxxxpd.concat([df1,df2],ignore_index=True)姓名 学号 语文0 张三 1001 801 李四 1002 852 王五 1003 903 张三 1001 804 赵四 1004 855 王五 1003 90
参考前面的(三)数据预处理→重复值处理方法。
xxxxxxxxxx# 重复行删除pd.concat([df1,df2],ignore_index=True).drop_duplicates()姓名 学号 语文0 张三 1001 801 李四 1002 852 王五 1003 904 赵四 1004 85
xxxxxxxxxxdf.to_excel(excel_writer, # 保存文件的路径,(路径+文件名称.xlsx)sheet_name='Sheet1', # 工作表的名称na_rep='', # 缺失值的填充float_format=None,columns=None, # 需要导出的列header=True, # 默认保留列索引,不需要Falseindex=True, # 默认保留行索引,不需要Falseindex_label=None,startrow=0,startcol=0,engine=None,merge_cells=True,encoding=None, # 编码格式,一般选择"uft-8"inf_rep='inf', # 无穷值的填充verbose=True,freeze_panes=None,)
xxxxxxxxxxdf.to_excel(r"C:\Users\Administrator\Desktop\学习笔记\5.Numpy_Pandas_Matplotlib\AsSave.xlsx",sheet_name= "测试",index=False)
使用pd.ExcelWriter()函数
xxxxxxxxxx# 保存文件的路径+文件名称.xlsxsavepath=r"C:\Users\Administrator\Desktop\学习笔记\5.Numpy_Pandas_Matplotlib\AsSaveMoreSheet.xlsx"# 声明一个读写对象myWriter = pd.ExcelWriter(savepath,engine="xlsxwriter")# 分别写入三张表,并命名,不要行索引df1.to_excel(myWriter,sheet_name="表1",index=False)df2.to_excel(myWriter,sheet_name="表2",index=False)df3.to_excel(myWriter,sheet_name="表3",index=False)# 保存写入的内容myWriter.save()
使用df.to_csv()方法
xxxxxxxxxxdf.to_csv(path_or_buf=None, # 保存文件的路径,(路径+文件名称.csv)sep=',', # 分隔符号na_rep='', # 缺失值的填充float_format=None,columns=None, # 导出的列header=True,index=True, # 行索引index_label=None,mode='w',encoding=None, # 编码格式,默认UTF-8,中文一般用utf-8-sig或者bgk编码compression='infer',quoting=None,quotechar='"',line_terminator=None,chunksize=None,date_format=None,doublequote=True,escapechar=None,decimal='.',)
xxxxxxxxxximport pandas as pd# 显示所有行列pd.set_option('display.max_columns', None)pd.set_option('display.max_rows', None)# 列对齐pd.set_option('display.unicode.ambiguous_as_wide', True)pd.set_option('display.unicode.east_asian_width', True)
xxxxxxxxxxrecent_date = df['date'].max()df[df['date'] == recent_date]# 或者dfNew = df[df['净值'] == df['净值'].max()]
xxxxxxxxxxdf.iloc[[0, -1]] # 第一行和最后一行df.iloc[0] # 第一行df.iloc[-1] # 最后一行
xxxxxxxxxxdata = df.loc[index, :]
data[ 列名 ] 取单列或多列,不能用连续方式取,也不能用于取行。
data.列名 只用于取单列,不能用于行。
data[i:j] 用起始行下标(i)和终止行下标(j)取单行或者连续多行,不能用于列的选取。
data.loc[行名,列名] 用对象的.loc[]方法实现各种取数据方式。
data.iloc[行下标,列下标] 用对象的.iloc[]方法实现各种取数据方式
pd.to_datetime:pandas的一个函数,能将字符串、列表、series变成日期形式
Timestamp:pandas表示日期的对象形式,
DatetimeIndex:pandas表示日期的对象列表形式
总结:
xxxxxxxxxx# 将字符串"2022-07-28"转成pandas日期类型datetime64[ns]df["日期"] = pd.to_datetime(df["日期"])# 去掉时间0:00:00,3种方法df["日期"] = pd.to_datetime(df["日期"], format="%Y-%m-%d") # 方式1,format指定格式df["日期"] = pd.to_datetime(df["日期"]).dt.date # 方式2,不建议,速度慢,效率低df["日期"] = df["日期"].str.split(" ", expand= True)[0] # 方式3,还是字符类型
xxxxxxxxxx# Timestamp('2022-02-25 00:00:00')df["日期"].strftime("%Y-%m-%d")
xxxxxxxxxx# 将日期设置成索引df = df.set_index('日期')# 统计2022年的数据,当日期是索引时才可行df['2022']# 按年、月阶段统计df['2022-01':'2022-07']# 如果统计具体某一天的数据,一定加locdf.loc['2020-01-31']# 统计具体某一天到某一天的数据df['2022-01-01':'2022-07-31']# 按天统计df1.resample('D')# 按月份统计df.to_period('M')# 按季度统计df.to_period('Q')# 按年统计df.to_period('A')# 按周对数量进行汇总df['数量'].resample('W').sum()# 按月汇总,默认每个月的最后一天,如果想要按照每个月的第一天展示日期, “M”改成“MS”df.resample('M').sum()# 按照季度统计,默认每个季度的第一天df.resample('QS').sum()df.resample('AS').sum()df.resample('AS').sum().to_period('A')df.resample('Q').sum().to_period('Q')df.resample('M').sum().to_period('M')