python学习笔记第7章:数据处理(pandas,numpy)
2.1 加载数据
2.1.1 定义DataFrame
import pandas as pd
df = pd.DataFrame() #定义一个空的DataFrame
df = pd.DataFrame(columns=['c1','总人数']) #新建DF,并指定列名
df = pd.DataFrame(index=[‘a,’]) #新建DF,并指定行名
df = pd.DataFrame(list1) #新建DF,值为list1
df = pd.DataFrame(游标) #将mongo或oracle查询结果转为df
df.set_index('c1',inplace=True) #设置某列为行索引,根据列名
df.set_index(['c1'],inplace=True) #同上,加了方括号
2.1.2 其他类型转df
sql数据库查询结果转df
data = cursor.execute(sql)
df1 = pd.DataFrame(data) #游标转为df
df1.columns =[“c1’, ‘c2’] #替换表头
复制df
df2 = df[[‘c1’,’c2’]]
2.1.3 读取表格
import pandas as pd
src = r'C:\Desktop\upload\考勤报表_1月.xlsx'
空值转换
df = pd.read_excel(src, keep_default_na=False)
新建/打开表格并设置表头
df = pd.read_excel(src,names=['c1','总人数','发送一次用户数'])
指定读取格式gbk,默认utf-8
df = pd.read_excel(src,encoding=’gbk’)
指定某列数据类型
df=pd.read_csv(src,dtype={‘c1’: str,’c2’:str}) #以指定类型读取
行索引与表头
df = pd.read_csv(src,index_col=0)
#在第一列前再加一列数字, 指定第一列做行索引,此时第一列将不参与计算
#不加的话,
df = pd.read_csv(src,header=0) #指定第一行做表头,缺省值,不用加
df = pd.read_csv(src,header=None) #表没有表头时使用这项
#写入到多个工作表时
写入到已存在的表
from openpyxl import load_workbook
ew = pd.ExcelWriter(src, engin='openpyxl')
ew.book = load_workbook(ew.path)
# df1 = pd.read_excel(src2)
df1.to_excel(excel_writer=ew,sheet_name="name")
ew.save()
ew.close()
写入到全新的表
ew = pd.ExcelWriter(src)
df1.to_excel(ew, sheet_name='sheet1', index=None)
ew.save()
指定读取的工作表
df1 = pd.read_excel(src,sheet_name = 'sh') #读取名为sh的工作表
df2 = pd.read_excel(src,sheet_name=1) #读取第二个工作表,从0计数
df3 = pd.read_excel(src, sheet_name=['python', 'student']) # 指定多个工作表名
df4 = pd.read_excel(src, sheet_name=[1, 2]) # 通过索引指定多个
df5 = pd.read_excel(src,sheet_name=['python',1])#可以混合的方式来指定
指定读取行列
df6= pd.read_csv(src, usecols=[0,2] ) #只加载第1列和第3列
df6= pd.read_csv(src, usecols=[‘A’,’C’] ) #只加载第A列和第C列
df6= pd.read_csv(src ,nrows=6) #只加载前6行
df6= pd.read_csv(src ,skiprows=6) #跳过前6行
df6= pd.read_csv(src ,header=6) #跳过前6行
其他
df7= pd.read_table(src, sep=’ ‘ )
#使用空格做csv或txt的分隔符,缺省逗号,读取txt文件时可能要指定sep
df8=pd.read_sql(‘sql语句’,数据库连接)
3.自动可视化数据
import pandas as pd
import pandas_profiling
src = r'C:\Users\zx\Desktop\find_query.csv'
df = pd.read_csv(src)
df.profile_report(title='Titanic Dataset')
2.2 读取数据
df.info() #查看表的概要信息
pd.set_option('display.max_columns', None) # 显示所有列
pd.set_option('display.max_rows', None) # 显示所有行
pd.set_option('max_colwidth', 100) # 设置value的显示长度为100,默认为50
2.2.1 读取表头
df.columns #读取表头
df.columns.to_list() #读取表头,并转格式为列表
df.columns.values.tolist() #读取表头,并转格式为列表,完全同上
2.2.2 获取全部数据
df.values #读取全部数据
df.head() #读取前n行数据,不加参数前5行
.tail()
2.2.3 获取行数或列数
df.shape #获取行数和列数,元组形式,
len( df ) #获取行数,不计入表头
df.shape[0] #获取行数,不计入表头
df.shape[1] #获取列数
2.2.4 获取整行或整列数据
读取行
df.loc[[0]] #读取第一行,loc行号可以数字,列名不行
df.iloc[0].values #读取第一行
df.iloc[ [0] ] #读取表头和第一行
df.loc[[0]] #读取表头和第一行,以列的形式显示
读取列
df.iloc[ : , [0] ] #读取第一列
df.iloc[ : , [2:5] ] #读取连续多列
df[ ['项目'] ] #根据列名读取列,可指定多列
df[['金额','项目']] #根据列名读取多列
df[ '项目' ] #根据列名读取一列,只能一列,结果返回数据类型,有时双方括号显示超出索引。根据列名读取列不能用loc
col=df['列名'].values.tolist() #列转化为列表
.index.tolist()
2.2.5 获取指定单元格数据(可以用单层或双层方括号,双层可指定多个,单层只能一个)
loc
df.loc[ [‘name’] [‘name’] ] #用行名和列名指定数据
df.loc[2, '项目1'] #用行号和列名指定数据
df.loc[[2]['项目1'] ] #用行号和列名指定数据
df.loc[2]['项目1']
loc行号可以用数字索引,列名必须字符串,
loc必须同时给出行索引和列索引,只给一个无法使用
iloc
df.iloc [0,0] #读取第一行第一列,表头不计数
df.iloc [0] [0] #读取第一行第一列
df.iloc [ [0] , [0] ] #读取第一行第一列
df.iloc[ 0:4 , 0:1 ] #读取前4行前两列
df.iloc[[0,2],[0]] #区别是,两层方括号可以指定多行/列,逗号隔开
df['金额'][0] #不用loc或iloc,与上面不同,先行后列。类似loc,列用列名,行用行号,双方括号会出错,超出索引
2.3 遍历
2.3.1 用行号和列号遍历1
for i in df.itertuples():
print(i[3]) #某列, 使用列序号,获取整行, 类型为元组
2.3.2 用行号和列号遍历2
for i in range(0 , len(df)): #len(df)总行数
for j in range(0,df.shape[1]): #df.shape[1]总列数
a = df.iloc[ [i] , [j] ]
print(a)
2.3.3 用行号和列名遍历1
注意, index没有括号, at后方括号, 而且第一列必须是数字索引列, 不能是数据列, 否则会报错
for i in df.index:
a = df.at[i,’c1’]
2.3.4 用行号和列名遍历2
for i in range(0 , len(df)):
a = df.loc[ i , ‘c1’ ]
2.3.5 map对单列执行操作
def foo(i): #i为指定列传入的数据
return i if i and pd.notna(i) else ‘haha’
df["c3"] = df["c3"].map(foo)
2.3.6 apply用于某几列或单列经过计算返回一个新列
def hebing(dd, a, b): #第一个参数代表df, 必须由的,
c1 = dd[a]
c2 = dd[b]
c3 = c1 if c1 != '' else c2
return c3
df["c3"] = df.apply(hebing, axis=1, args=('c1列名', 'c2列名'))
#如果只有一个参数, 最后要写逗号
#c1, c2经过函数hebing的计算, 赋值给c3
2.3.7 applymap用于对所有列的所有数据执行同样操作
df =df.applymap(lambda x : x.strip() ) #所有数据去掉首尾空格
2.4 查找
2.4.1 条件筛选
df.query(‘1000 > 金额 > 200’) #筛选出金额列大于1000小于200的值
df.query(c1>1000 and c1<200).query('c2>10') #在多个列筛选
df.query("c1 == 'young' ") #字符串
df.query("c1 == 'young' ", inplace=True) #直接在原数据上修改
df.query('(c1 < c2) & (c2 < c3)') #列与列比较
df.query(f"c1 == '{i}' ")[“c3”] #查询结果只看c3这一列
df [ df ['金额']>6000 ]
#筛选出金额列数值大于6000的行,如果不加外面那层df会报错
df[ (df['金额']>6000) & (df[‘name]=’young) ]
#根据多个条件筛选,每个条件在小括号内,&,|
df[‘name’].isin([31,32]) #查找年龄列包含31或32的
df[df[‘name’].isin([31,32])] #输出年龄列包含31/32的所有行
df . isin ([31,32]) #查找全表包含31或32的
df.loc[df[‘c1].str.contains(‘a|b’)] #模糊查询c1列含有a或b的
2.4.2 去重
df[‘c1’].unique()
2.4.3 展示行/列非空值个数
df.count( ) #展示每列的非空值个数
df.count(axis=1) #展示每行的非空值个数
df[‘name’].count() #展示name列非空值个数
2.4.4 统计某个数值出现次数
#统计name列每个名字出现的次数,显示顺序按照比例降序排序,缺省值
df [ ‘name’].value_counts()
#统计name列每个名字的占比,显示顺序按照比例降序排序,缺省值
df [ ‘name’].value_counts(normalize =True)
#统计name列每个名字的占比,显示顺序按照原来的顺序排序
df [ ‘name’].value_counts(normalize =True,sort=False)
2.5 表连接
横向连接,vlooup
方式一:指定表二要加载的字段
pd.merge(data , data2 [['编号','c2']] , how='left' , on='编号')
方式二:(先把要加载的字段取出来,再做连接)
df2 = df2[["学号", "姓名", "性别"]]
pd.merge(df1, df2,how=’left’ , on="学号")
方式三:连接全部字段
df3 = df1.merge(df2, how='left' , on = '学号') 需要赋值保存
方式四:(不指定how,默认内连接)
df1.merge(df2).drop_duplicates() 连接全部字段, 且删除重复字段
left_on = ‘左表要用的字段’
外连接:outer
内连接:inner, 默认值
纵向连接(两表合并union all)
pd.concat([df1,df2])
#df2的数据拼接到df1下方
pd.concat([df1,df2],igonre_index=True)
# 连接后行号重新计数
pd.concat([df1,df2],igonre_index=True).drop_duplicates()
# 连接后删除重复行
2.6 修改数据
2.6.1 修改
修改指定单元格数据
df.loc['fenju']['总人数'] =5
#修改整列
df['c1'] = df['总人数'] - df['c1']
df['c1'] = df['总金额'] - 1000 #整理数值减1000
df["c1"] = df["c1"].map({"男":1, "女":0}) #把该列男替换为1
df["c1"] = df["c1"].map(test) #对整列使用函数test处理
df["c1"] =df["c1"].apply(lambda x : x+2 )
data[["c1","c2"]].apply(test, axis=0) #对多列使用函数
#根据条件筛选,修改整列
#update set where
df.loc[df.c1==’8万’,'c2'] = 1 #c1列为8万的,c2列改为1
df.loc[(df.Exam<48)&(df.Total>50),'Final']=44 #多个条件筛选
df.loc[df[‘c1’].isin(['A', 'B']), 'c2'] = 'A级' #c1列等于A或B的,c2改为A级
df.loc[df['c1'].str.contains('c|d']) ,'名称地址匹配'] = 1 #模糊匹配c1列含有c或d的修改
改列名
df.columns = [‘c1’,’c2’,’c3’] #替换整个表头
df.rename(columns={'原列名':'新列名','b':'B'}, inplace = True)
#原列名冒号新列名,可改多列,inplace=True 或者赋值
改行名
df.rename(index = {'原行名':'新行名'}) #参考改列名
df.rename(columns={'原列名':'新列名},index = {'原行名':'新行名'})
#同时改行列名称
修改整列数据类型
df[‘列名’].dtype #查看某列数据类型
data['项目'].astype(int) #同下,区别转int时为int32,下面int64
data['项目'].apply(str) #将编号列的格式改为str,[int,float]
替换整列
df[ '其他'] = df[ '项目'] #把其他这一列的数据替换为项目的数据,不换表头
替换
df.replace(np.NaN , 0) #全表空值换为0
df.replace(no,yes,inplace=True) #全表的no换成yes,并保存
df[‘name’].replace(no,yes,inplace=True) #在指定列进行替换并保存
df[‘name’].replace( [no,other] , yes) #指定列上多对一替换
df.replace({no : yes , i : you}) #全表多对多替换
df.replace(to_replace=r"^\s*$", value="", inplace=True, regex=True) #正则替换为空
2.6.2 新增数据
追加一行
def pd_append():
src = r'C:\Users\young\Desktop\abc.csv'
col_df =[]
df = pd.DataFrame()
data =
for i in data:
col_df.append(
()
)
df = df.append(col_df)
df.columns = [] #表头
df.to_csv(src,index=None)
‘以下效率低,已启用’
df=df.append(c.find_one({'_id':ObjectId(row)}),ignore_index=True)
#追加一个字典型数据,必须要写成df = df.append , 否则不会保存
data = {'c1':i,'总人数':count_all} #字典类型,键是行名称,值是数据
df=df.append(data,ignore_index=True) #把字典追加到df,使用自动索引
增加一列
如无位置要求
df[‘c1’] =
df.insert( 2, ‘新列名’,[‘ni’,’hao’,’a’])
#在第二列后插入一列,插入位置在第三列,列名‘新列名’,每行数据ni hao a
df[新列名’]=[‘ni’,’hao’,’a’] #新增一列,位置在最后
df['未发送'] = df['总人数'] - df['yifa'] #新增一列,数据来自两列相减
df.eval(‘c3=c1-c2’,inplace=Treu) #同上
2.6.3 删除数据
删除行
df.drop('apps') #根据行名删除行,参数axis=0
df.drop( ['apps' ] ) #根据行名删除行,可在方括号指定多列
df.drop ( index=[‘行名’] ) #根据行名删除行
df.drop ( df.index [ [1,2,3] ],axis=0) #根据行号删除行
df [ df[‘year’]<30 ] #根据条件删除行(若果要删除年龄30及以上的,就取年龄30以下的,赋值给df
删除列:
df = df.dorp('apps', axis=1)
df = df.drop( ['apps' ], axis=1 )
del df1['A','B'] # 删除A,B列,会就地修改
df1.drop(df1.columns[0:4], axis=1, inplace=True) # 删除前4列,
(默认需要赋值给df,否则不改变df,相当于新开辟一块内存区域,并且还要保存到文件to_csv。改变df两种方式
1.赋值,df = df.drop(‘apps’)
2.用参数inplace=True, df.drop(‘apps’,inplace=True)
删除全部空格
df.replace('\s+','',regex=True,inplace=True)
2.6.4 空值处理(NaN)
查看空值
df.info() #查看全部信息,包含缺失值概览
df.isnull() #每列都显示为True或False,False代表缺失
空值判断
if pd.isna(c1): #如果是空值, 返回true
if pd.notna(c1): #如果不是空值, 返回true
上面两个函数只能判断pandas空值,不能判断空字符串,判断非空需要这样
if c1 and pd.notna(c1):
空值替换(需要赋值)
df = df.fillna(‘’) #将全部空值(NaN)替换为空
df = df.fillna(0) #将全部空值(NaN)替换为0
df.fillna({‘name’:’li’,’year’:’20’}) #替换name和year两列的空值
df.fillna({1:0, 2:0.5}) #对第一列nan值赋0,第二列赋值0.5
df.fillna(method='ffill') #在列方向上以前一个值作为值赋给NaN
df[0].ffill() #对第一列上的合并单元格进行填充
#用一列替换另一列的空值
df["c1"].fillna(df["c2"], inplace=True) #c2列替换c1列上的空值
df['c1'] = df['c2'].fillna(df['c1']) #同上
df['c1'] = df['c1'].mask(df['c2'].notna(), df['c2']) #同上
空值删除
df.dropna() #删除数据中含有空值的行,哪怕该行只有一个空值
df.dropna(how= 'all') #删除整行都为空值的行
df.dropna(subset=["经度", "纬度"]) #删除指定行为空值的行
df.dropna(axis=1) #删除数据中含有空值的全部列
2.6.5 重复值处理
df.drop_duplicates( ) #删除重复行,保留第一行,每行所有字段一致算重复
df.drop_duplicates(subset=’name’) #删除重复行,name列重复就算
df.drop_duplicates(subset=[’name’,’year’])
#删除重复行,name和year两列都重复算重复
df.drop_duplicates(keep=’last’) #删除重复行,保留最后一行
df.drop_duplicates(keep= False) #删除重复行,不保留重复的行
2.7 处理数据
df.descripe() #自动对数值列求均值,最大值等
计算
df[‘c1’] + df[‘c2’]
df[‘c1’] + 2
+ - * / > = !=
转置
df = df.T 行列转置
拆分列
df1 = df[‘ca’].str.split(expand=True) #以空格拆分列
聚合函数(sum可替换为mean均值,max,min,median中位数,mode众数var方差,std标准差,quantile(0.75)分位数,)
df.sum() 对所有数值列求和
df.sum(axis=1) 对所有行求和
df[ ‘列明’].sum() 指定列或行求和
排序 (缺省空值排最后,na_position=’first’将空值排在最前)
df.sort_values(by = [列明’],ascending=False) #该列降序排列,缺省升序
(by=[列1,列2],ascending=[False,True]) #第一列降,第二列升
区间切分
pd.cut(df[‘year’],bins=[0,10,20,30])
#划分左开右闭区间(开(不等于,闭[等于),(0,10],(10,],显示year列每个数字所在的区间
pd.qcut(df[‘year’],3)
#指定需要的区间数,系统自动划分,划分规则每个区间里的数据尽量接近
结构重塑
df.stack( ) #数据转为树形结构
df.unstack() #数据从树形结构转为表格结构
合并单元格处理
df[0].ffill() #对第一列上的合并单元格进行填充
在列上拆分合并的单元格
df.reset_index() #所有列上合并的单元格都拆分掉
df.reset_index(level=0) #拆分第一列上合并的单元格,缺省拆分全部列
df.reset_index(inplace=True) #在原数据上修改,缺省Fasle
重置行号
df.reset_index(drop=True) #重置后删除掉原来的行索引,缺省Fasle
相关性(相关系数)
df.corr( ) #全表相关性
df[‘c1’] . corr( df [‘c2’] ) #两列相关性
2.8 数据分组
df.groupby(‘c1’).count() #c1单列分组,统计其他列行数
df.groupby(‘c1’).max() #c1单列分组,其他列取最大值
df.groupby([‘c1’,’c2’]).sum() #多列分组,对其他数值列求和
df.groupby(‘c1’)[‘c3’,’c4’].sum() #分组后,对指定列求和
#聚合函数均可用
#对c1列分组, 找出数量大于1的组
df.groupby('c1').size().reset_index(name='counts').query('counts>=2')
num=df.groupby('c1').size() #统计每个分组的行数
x=num.index.tolist()
y=num.values.tolist()
以series形式分组(没什么区别)
df.groupby(df[‘c1’])[‘c3’].count()
aggregate方式分组
可对每列使用不同的聚合函数,可对单列使用多个聚合函数
df.groupby(‘c1’).aggregate([‘count’,’sum’])
#c1分组,分组后对每列使用count,sum两个聚合函数
df.groupby(‘c1’).aggregate({‘c2’:’count’,’c3’:sum’})
#分组后对c2列计数,c3列求和,字典形式,列名:函数
分组后若列名不整齐,使用重置索引普通分组与agg分组都可用,写在最后
df.groupby([‘c1’,’c2’]).sum().reset_index()
2.9 数据透视表(长宽表转换)
宽表转长表(类似行转列,多了一步把行名称等添加多个)
方式一:
df.set_index([ ‘要保留的列名’,’一般是id,name’])
df.set_index([ ‘保留的列名’,’name’]).stack( )
df.set_index([ ‘保留的列名’,’name’]).stack( ).reset_index( )
方式二:
df.melt( id_vars= [ ‘要保留的列名’,’name’],
var_name=’新列名’,
value_name = ‘新数据列名’)
数据透视表(长表转宽表[类似列转行])
df.pivot_table(index = [‘保持不变,多个合并成一个的列名’],
columns=’要从列换成行的列’,
values=’要从列换成行的列,数值列’)
2.10 保存
df.to_excel (src,index=None,encoding=’gbk’,columns=[‘c1’,’c2’])
#把df里的内容保存到src的第一个工作表
# encoding=’gbk’ ,设置编码方式,缺省格式utf-8
#sheet_name=’name’,设置工作表名称,缺省Sheet1
#index=None,不把第一列导入到表格,一般要用.读取文件时如果没加index_col=0 , 第一列是行号,读取文件一般不加index_col,因为要用行号
#columns=[‘c1’,’c2’],只导出指定列,缺省全部列
#na_rep = 0,缺失值填充为0,缺省不处理
#inf_rep = 0,无穷值填充为0,缺省不处理
#sep=’,’ 逗号作为分隔符
#以上参数csv、excel基本通用
#写入到多个工作表时
写入到已存在的表
from openpyxl import load_workbook
ew = pd.ExcelWriter(src, engin='openpyxl')
ew.book = load_workbook(ew.path)
# df1 = pd.read_excel(src2)
df1.to_excel(excel_writer=ew,sheet_name="name")
ew.save()
ew.close()
写入到全新的表
ew = pd.ExcelWriter(src)
df1.to_excel(ew, sheet_name='sheet1', index=None)
ew.save()
压缩保存
compress = dict(method='zip',archive_name='保存文件名及路径')
df.to_csv('call.zip', index=None,compression=compress)
#call.zip压缩文件名
2.11 numpy
import numpy as np
x = np.arange(-10 , 10 , 0.1) #生成一个列表,从-10开始,递增0.1
y = np.sin(x) #使用sin函数求x中每个元素正弦值
x.dtype() #查看x的数据类型
x=linspace(0, 9, num=50, retstep=False, dtype=int)
#前两个参数同arange,第三个参数指定在该区间内生成多少个数据endpoint=False,不包含右区间,缺省包含
dtype=int指定生成数据的类型,缺省为自动

浙公网安备 33010602011771号