《深入浅出Pandas:利用Python进行数据处理与分析》——第2部分 Pandas数据分析基础

1.数据读写

支持各种数据的读取:CSV、HTML、EXCEL、SQL等,部分读取函数,如:
pd.read_excel
pd.read_csv
pd.read_table
pd.read_hdf
pd.read_sql
pd.read_json
# 相对的,输出函数如下:
df = pd.read_excel('./datasets/team.xlsx')
df.to_csv
df.to_excel
df.to_html
df.to_sql
df.to_json
# 读取与输出参数均可自定义设置,例如输出路径、表头、列号、编码等

mysql连接和读取操作

import pymysql
from sqlalchemy import create_engine  
db = create_engine('mysql+pymysql://127.0.0.1')  # mysql应知应会练习的数据
df = pd.read_sql('SELECT * FROM exercise.Vendors', db)

CSV读取:最为常见,基本语法及常用的参数

# 基本读取
df = pd.read_csv(data)
# CSV分隔符不为逗号时,可自定义指定的分隔符,分隔符有两个参数,sep和delimiter,指定delimiter时,sep失效
df = pd.read_csv(data, sep='  ')  # 使用两个空格最为分隔符
# 传入的CSV有时候有表头,有时候没有表头,甚至表头不为第0行,默认情况下为第一行作为表头,支持自定义
df = pd.read_csv(data, header=0)  # 默认情况下header为0,第一行数据【不是文件第一行,会忽略掉空行和注释行】
df = pd.read_csv(data, header=None)  # 无表头的情况
# 当然,可以自定义输入的表头
df = pd.read_csv(data, name=['name1', 'name2',..., 'namen'])  # 注意,name的大小和数据列数相同,此时默认header=None
# 上面是列表头,索引默认情况下为自然索引,也可自定义,参数位index_col,支持多种情况
df = pd.read_csv(data, index_col=0)  # 第一列作为索引,列名,列名列表均可
# 支持数据非全部导入,使用Usecols
df = pd.read_csv(data, usecols=[0,3,2])  # 按照索引读取,顺序无关,且不会改变原始顺序,,列名,列名列表均可

布尔值问题(true_values, false_values):支持将指定的文本内容转换位布尔值
过滤指定行(skiprows):单一数字时,跳过前多少行,列表时跳过指定的行
读取指定大小的行(nrows):读取nrows行,此参数和skiprows参数结合使用,可以实现大文件多次小批量读取。此功能可以直接使用iterator参数和chunksize函数实现
read_csv功能模块多样化,多help查询,记是记不住的,关键是要用,有个基本概念,遇到的时候就不会单独再实现了。
其它数据读取操作同理,多help,或直接跳转到源码查看,EXCEL需要注意sheet问题
*一个有趣的:pd支持直接创建包含数据的压缩文件,同理,也可以读压缩的文件

df.to_csv('test.zip', compression={'method':'zip', 'archive_name':'test.csv'})
df = pd.read_csv('test.zip', compression={'method':'zip', 'archive_name':'test.csv'})

2.基本操作

二维矩阵,矩阵怎么操作?可以单看行,也可以单看列,也可多行,或者多列,总之,矩阵能够操作的,pandas都可以实现,具体怎么操作就多练多help,多搜索引擎。

df.index.name   # 名称
df.index.array  # 数组
df.index.dtype  # 类型
df.index.shape  # 形状
df.index.rename  # 重命名
df.index.to_list  # 转为列表

使用VSCODE等IDE工具,借代码补全功能,见名知大致意,例如:
在这里插入图片描述
支持数学统计等运算,例如均值、求和等一些统计函数。

位置计算

df.Q1.diff()   # 与前一个数据的差值
df.Q1.diff(-1)  #负数表示后一个
df.Q1.diff(2)   # 与前面移位两个的差值
df.loc[:5,'Q1':'Q4'].diff(axis=1)  # 纵向操作,即行数据比较

移位

df.shift()  # 整体下移
df.shift(3)  # 下移三位
df.shift(-1)   # 上移一位
df.loc[:5,'Q1':'Q4'].shift(axis=1)  # 右移一位

排序(排名)

df.head().rank()
df.head().rank(axis=1)
df.head().rank(pct=True)  # 转换为0-1间的数

数据选择

df.Q1  # 单列
df['Q1']  # 单列,返回series
df[['Q1','Q2']]   # 多列,返回dataframe
df.loc[1]  # 第2行,索引从0开始的
df[1:10]  # 切片选择行
df.loc[:, 'Q1':'Q3']  # 切片选择列
df.iloc[1]  # 支持纯数字索引
df.loc[2,'Q1']  # 取某一个具体的值
df.at[2,'Q1']  # 同上
df.iat[0, 4]  # 支持纯数字索引
df.get('name', 1)  # get,获取,类似字典手段
df.truncate(before=3,after=5)  # 截取字段,开区间截,闭空间留,示例留下索引为3到5的数据【包括3和5的索引】

3.高级操作

逻辑运算、比较筛选、函数、数据筛选等:

df.index==1   # 索引是否为0,返回布尔结果,和原矩阵大小一致
df[df.index==1]   # 返回索引为1的行
df.loc[:, 'Q1':'Q4']>40  # 判断选择的数据中是否大于40
df[(df.loc[:, 'Q1':'Q4']>40).all(1)]   # 筛选数据
max(df.Q1)   # 最大值
df[df.Q1.map(lambda x: x> 40)]  # lambda函数筛选
# 除了之间使用比较符号进行比较之外,还可以使用比较函数
df.ne() # !=
df.le()  # <=
df.lt()  # <
df.ge()  # >=
df.gt()  # >

查询:df.query(expr)

支持直接输入各种查询判断条件的表达式

# df.query(expr),支持直接输入各种查询判断条件的表达式
df.query('Q1>20')  # 筛选Q1>20的数据
df.query('Q1==Q2')  # 筛选
df.query('team!="c"')  # 包含字符串的表达式
# 支持变量引入@
a = 2
df.query('Q1 > @a+40')

筛选及类型转换

# 筛选df.filter
df.filter(items=['Q1', 'Q2'])  # 过滤,选择两列
df.filter(items=['Q1'])  # 过滤,选择一列
df.filter(regex='1$', axis=0)  # 正则,横向操作(对列操作),索引名以1结尾的
df.filter(like='Q', axis=1)  # 统配,纵向操作,筛选列名中有Q的
# 按数据类型查询
df.select_dtypes(include=['int64'])
# 类型转换astype
df.astype({'Q1':'string'})   # 将Q1列的数字转换为字符串

数据排序

# 数据排序
df.sort_index(ascending=False)  # 索引排序,ascending为排序参数,默认为True,表示升序,False为降序
df.sort_index(axis=1, ascending=False)  # 纵向排序,即列索引方向,对行数据排序,列字段排序
df.Q1.sort_index()   # 单独某列按照索引排序
df.reindex(index=[i for i in range(0,20,3)])  # 自定义列索引筛选
df.Q1.sort_values()   # 数值排序
df.sort_values(by='Q1')  # 数值排序,同上
df.sort_values(['Q1','Q2'], ascending=[True, False])  # 多数值排序,支持单独设定升序或者降序
df.index.names = ['index_name']  # 索引起名
df.reindex(df.name.sort_values().index)  # 按照排序的索引输出数据
df.nsmallest(2,columns='Q1')  # 选择最小的2个,按照Q1排序
df.nlargest(2,columns=['Q1','Q2'])  # 选择最大的2个,按照Q1/Q2排序

数据修改【列】

# 数据修改
# 数据的修改和数据的检索筛选基本类似,表达式右边需赋修改的值
df.loc[1, 'team'] = 'D'  # 将指定位置的信息改为'D'
df[df.Q1.lt(60)]['Q1'] = 60  # 将小于60分的成绩改为60, 较新版本pandas会告警,未实际修改
df['Q1'][df.Q1.lt(60)] = 60  # 将小于60分的成绩改为60, 较新版本pandas会告警,实际已修改
df.loc[df[df.Q1.lt(60)].index,'Q1'] = 60  # 将小于60分的成绩改为60,无告警,按照告警提示的使用loc进行修改
# 或者
df.loc[df.Q1<60, 'Q1'] = 60
df.Q1.replace(60, 6, inplace=True)  # 将60数值改为6,且原地修改(inplace),
df.Q1.replace([6,61],[60,62], inplace=True)  # 支持列表一一对应修改,也可支持字段对应修改,或者正则修改
df.replace(regex=['L.*'], value='new')  # 正则
df.fillna(1)  # 使用数字1填充无效值,或者其它方法,help查看method : {'backfill', 'bfill', 'pad', 'ffill', None}, default None, 
df.rename(columns={'Q1':'Q11'})  # 修改表头(列名)
df.rename(index={0:'x', 1:'y'})  # 修改索引(索引名)
df['total'] = df.select_dtypes(['int']).sum(1)  # 按类型选择数据,且求和,新增列
df.insert(len(df.columns), 'total2', df.select_dtypes(['int']).sum(1))  # 使用df.insert新增加列

链式方法:df.assign(expr)

通过非赋值的方法临时增加新列,对原数据没有影响,待确定后再赋值修改

df.assign(total=df.select_dtypes(['int']).sum(1))  # 使用assign,非通过赋值的方法新增加列,对原数据没有影响
df.assign(total=df.select_dtypes(['int']).sum(1), Q5=100)  # 同时增加两列,或者
df.assign(total=df.select_dtypes(['int']).sum(1)).assign(Q5=100)
df.assign(tag=(df.Q1>df.Q2).map({True:'及格', False:'不及格'}))

eval方法新增加列

同query类似,允许传入字符命令

df.eval('total=Q1+Q2+Q3+Q4')

数据修改【行】

df.loc[100] = ['tom', 'A', 88, 88, 88, 88]  # 新增加一行
df.loc[max(df.index)+1] = ['jack', 'B', 77, 77, 77, 77]  # 新增加一行,自动计算索引

数据合并【列】

数据合并,列追加,将两个dataframe数据在横方向合并为1个
两种方法,但第一种不推荐【未来新版本或会移除】

df.append(df)  # he frame.append method is deprecated and will be removed from pandas in a future version.
pd.concat([df, df])
tf = df.assign(total=df.select_dtypes(['int']).sum(1))
pd.concat([df, tf], ignore_index=True)  # 重拍索引
pd.concat([df, tf], ignore_index=True, join='inner')  # 仅合并相同列

数据删除

df.pop('Q1')  # 删除掉Q1列,且返回Q1列的值
df.dropna()  # 行数据只要有缺失值就删除
df.dropna(how='all')  # 全无值才删除,与之相反的是any
df.dropna(1)  # 列数据,有空值删除
df.dropna(thresh=2)  # 删除至少有两个缺失值的数据
df.dropna(inplace=True)  # 删除生效,原地修改

数据标记(where/mask)

df = pd.read_excel('./datasets/team.xlsx', usecols=['Q1','Q2','Q3','Q4'])  # 选择指定列
df = pd.read_excel('./datasets/team.xlsx').select_dtypes(include='number')  # 仅保留数字列
# df.where将不满足条件的替换
df.where(df<60,'及格')  # 保留满足条件值,不满足的用'及格'填充,默认用NaN填充
df.where(df>=60, '不及格')  # 标记不及格的
# df.where有个弊端,只能替换不满足条件的值,不能替换满足条件的值,numpy.where可以实现这个功能
import numpy as np
np.where(df>=60, '及格','不及格')
df.assign(avg=df.mean(1)).assign(tag=lambda d:np.where(d.avg>=60, '及格', '不及格'))

# df.mask将满足条件的进行替换,与df.where正好相反
df.mask(df>60,'及格')

数据迭代

df = pd.read_excel('./datasets/team.xlsx') 
# 1.使用for循环语句可对数据进行访问和操纵,或者使用zip打包数据
for i,n,q in zip(df.index, df.name, df.Q1):
    print(i,n,q)
# 2.使用iterrows,items
for index, row in df.iterrows():  # 将数据迭代为索引和值,类似于字典的items
    print(index, row['name'], row['Q1'])
for index, row in df.items():  # 将数据迭代为索引和值,本身也有items,但返回为(列名,本列数据)
    print(index, row, end='\n\n')
# 3.使用itertuples
for row in df.itertuples():  # 生成nametuples类型数据【速度最快】
    print(row.Index, row.name, row.Q1)  # 使用a.b的方式读取
# 4.按列迭代
for col in df:
    print(df[col])

函数应用

  • pipe() 应用在整个数据上(DataFrame or Series)
  • apply() 应用在DataFrame的行或列,默认为列
  • applymap() 应用在DataFrame的每个元素中
  • map() 应用在整个数据上(DataFrame or Series)的一列的每个元素中

pipe【盲区】【整体数据】

逻辑图,摘自《深入浅出Pandas:利用Python进行数据处理与分析》
在这里插入图片描述
使用自定义的fun函数处理数据,链式编程

df = pd.read_excel('./datasets/team.xlsx') 
# pipe,管道方法
def add_mean(rdf, n):
    df = rdf.copy()
    df = df.loc[:,'Q1':'Q4'].applymap(lambda x:x+n)  # 选择的数据分别加上n
    df['avg'] = df.loc[:,'Q1':'Q4'].mean(1)  # 求均值
    return df

df.pipe(add_mean, 0) # 调用,这样可以封装函数,实现处理函数的复用
df.pipe(lambda tf,x,y:tf[tf.Q1.ge(x) & tf.Q2.ge(y)], 80,30)  # 使用lambda函数

apply【行列】

逻辑图,摘自《深入浅出Pandas:利用Python进行数据处理与分析》

在这里插入图片描述

df = pd.read_excel('./datasets/team.xlsx') 
# apply方法
df.name.apply(lambda x:x.upper())
# 经典的去掉最高和最低分求取平均值
def my_mean(s):
    return (s.sum()-s.max()-s.min())/(s.count()-2)

df.select_dtypes(include='number').apply(my_mean)  # 求取Q1:Q4每一列的平均值
df.select_dtypes(include='number').apply(max, axis=1)  # 每一行的最大值

applymap【元素】

逻辑图,摘自《深入浅出Pandas:利用Python进行数据处理与分析》
在这里插入图片描述

df = pd.read_excel('./datasets/team.xlsx') 
def mylen(x):
    return len(str(x))

# 三个语句效果相同
df.applymap(lambda x:mylen(x))
df.applymap(lambda x:len(str(x)))
df.applymap(mylen)

map【列上元素】

df = pd.read_excel('./datasets/team.xlsx') 
teams = {k:'{}_class'.format(i) for i,k in enumerate(set(df.team))}
df.team.map(teams)  # 映射改变每个值
df.team.map('I am a {}'.format, na_action=None)
df.team.map(lambda x:x.lower())

agg【聚合函数】

df = pd.read_excel('./datasets/team.xlsx') 
# agg,聚合函数
df.select_dtypes(include='number').agg(max, axis=1)  # 每一行的最大值,仅数字
df.select_dtypes(include='number').agg([sum, min, max])  # 每一列的和、最小、最大值,仅数字
df.agg({'Q1':[sum, max], 'Q2':[sum,min]})  # 多个聚合

transform

df = pd.read_excel('./datasets/team.xlsx') 
# transform,返回一个与自身长度相同的数据
df.transform(lambda x:x*2)
import numpy as np
df.transform([np.sqrt, np.exp])
df.select_dtypes(include='number').transform(abs)
df.groupby(['team']).sum()  # 分组后求和
df.groupby(['team']).transform(sum)  # 同样是分组后求和,但返回的是原数据的结构

copy

类似于Python中的copy函数

df = pd.read_excel('./datasets/team.xlsx') 
tf = df.copy(deep=True)  # 默认为深拷贝

4.总结

尽管是Pandas的重度使用者,但确实仅用之皮毛,很多方法和函数属于首次遇见,集思广益不少,瓶颈不少轻松突破,例如df.where或者df.mask方法等,以前是全是仅依赖map实现,例如map(lambda x:'及格‘ if x>=60 else ‘不及格’)等。
多查:搜索引擎查
多练:孰能生巧
多看官方文档或相关教程:其它各个渠道的介绍资料深度较浅,高级功能还是需要多查官方文档或教程,首推官方文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raykingl

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值