化身天使的博客

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指定生成数据的类型,缺省为自动

posted @ 2021-08-07 20:02  化身天使  阅读(470)  评论(0)    收藏  举报