Pandas01: Pandas01
文章目录
- 内容回顾
- 1 数据的读取和保存
- 1.1 读写Excel文件
- 1.2 读写CSV
- 1.3 读写Mysql
- 2 DataFrame 数据查询
- 2.1 筛选多列数据
- 2.2 loc 和 iloc
- 2.3 query查询方法和isin 方法
- 3 DataFrame增 删 改数据
- 3.1 增加一列数据
- 3.2 删除一行/一列数据
- 3.3 数据去重
- 3.4 数据的修改 直接改/replace方法
- 3.5 apply 通过自定义函数来修改数据
- series的apply方法
- dataframe的apply
- df的applymap方法
- 4 修改行列索引
内容回顾
Series/DataFrame
- 创建的方法
python">pd.Series(data = 字典, 列表,ndarray ,index = )
pd.DataFrame(data = 字典{列名:[值]} [[]],[()] ,index = ,columns=)
Series 一列数据, 一定有Index 行索引
DataFrame 是二维数据, 一定有index 和 columns 列名
- 常用的属性
python">s.index
s.values
s.shape (行数,)
df.index
df.columns
df.shape (行数, 列数)
df.values
- 常用方法
python">head()
tail()
s.to_frame()
s.to_list()
# 统计方法
min max mean median中位数 quantile 分位数 sum std标准差 describe()
df.info() 数据条目数, 每一列非空值的数量, 每一列数据的类型
# 修改数据的方法
drop_duplicates()
sort_values( ascending = False)
sort_index()
unique,nunique()
修改数据的方法的共同参数 inplace = False默认值
- 布尔索引取值 类似与SQL 的where条件
series[s == > < != 值]
df[s == > < != 值]]
如果条件有多个 条件需要用()包起来 (条件1) & | (条件2)
- 两个Series 两个DF之间进行计算
- 和具体的值进行计算 每一个值都会和 要计算的值进行计算 不需要遍历
- s 和 S df和df 使用行索引对齐
1 数据的读取和保存
1.1 读写Excel文件
写入数据到Excel
python">import pandas as pd
data = [[1, '张三', '1999-3-10', 18],[2, '李四', '2002-3-10', 15],[3, '王五', '1990-3-10', 33],[4, '隔壁老王', '1983-3-10', 40]]
student_df = pd.DataFrame(data,columns=['id','name','birthday','age'])
# student_df.to_excel('out/students2.xlsx',index=False,header=False)
student_df.to_excel('out/students3.xlsx',index=False,sheet_name='学生信息表')
一定要传的是文件的路径 (xlsx 新的格式 xls 老的格式)
index 默认是 True 会保存df的行索引 改成False 不存
header 默认是 True 会保存df的列名 改成False 不存
sheet_name 指定Excel文件的工作表的名字, (在Excel 表格软件中在底栏修改 工作簿(一个Excel文件) 工作表(一个工作簿可以有多张表))
从Excel文件中读取数据
python">pd.read_excel('out/students.xlsx',index_col=0)
#%%
pd.read_excel('out/students2.xlsx',header=None)
#%%
df_dict = pd.read_excel('out/students3.xlsx',sheet_name=['学生信息表','表2'])
type(df_dict['表2'])
一定要传的是路径
index_col = 哪一列数据作为读取出来的df的行索引
header = 哪一行数据作为读取出来的df的列名 None 自动给一个从0开始的
sheet_name 可以是一个数值, 字符串(表名), 列表(工作表序号或者工作名字组成的列表)
- 如果是一个int str 返回一个指定的工作表对应的DataFrame
- 如果传入的是别表, 返回字典 {工作表名: 对应的df对象}
1.2 读写CSV
python"># 保存数据 为CSV格式
student_df.to_csv('out/students2.csv',index=False,sep='\t')# 读取CSV数据
pd.read_csv('out/students.csv')
#%%
pd.read_csv('out/students2.csv',sep='\t')
index,header 用法和读写Excel时一样
sep 参数指定分隔符, 默认是逗号 (CSV comma seperator values) 可以改成用制表符来作为每一列的分隔符
- 保存数据的是时候如果修改了分隔符, 读取的时候需要指定相同的分隔符
1.3 读写Mysql
用到两个三方库 sqlalchemy 和 pymysql
python">from sqlalchemy import create_engine
# 创建数据库链接的engine
engine = create_engine('mysql+pymysql://root:root12345@localhost:3306/test1?charset=utf8')
# 把数据保存到Myql
student_df.to_sql('stu',engine,if_exists='append',index=False)#从Mysql里读取
pd.read_sql('stu',engine.connect(),columns=['id','name'])
保存数据的时候, if_exists=‘append’ 如果表已经存在了 如何处理, append 追加 replace 替换
read_sql 讲义上写的是engine 当前的版本是engine.connect() api发生了改变
2 DataFrame 数据查询
2.1 筛选多列数据
df[‘列名’] 从dataFrame中选中一列数据 返回 Series
- series里有一个属性 name 保存DataFrame这一列的列名
如果想选择多列
df[[列名列表]] → DataFrame
df[‘列名’] 和 df[[‘列名’]] 的区别
- 传入的是字符串 返回的是Series
- 传入的是列表 返回是DataFrame
2.2 loc 和 iloc
行列筛选数据的属性
df.loc [行名称, 列名称] df.iloc [行序号, 列序号]
- 行列的操作, 可以传一个值, 也可以传列表, 也可以是切片
- 如果是切片操作 loc 左闭:右闭 iloc 左闭:右开
df.loc[行名称/ 行名称列表 / 行名称的切片] df.iloc[行序号/ 行序号列表 / 行序号的切片]
df.loc[:,列名称/ 列名称列表 / 列名称的切片] df.iloc[: ,列序号/ 列序号列表 / 列序号的切片]
loc 控制行的部分, 可以使用布尔索引
python">#区域是广安门租房的户型面积和价格
df.loc[df['区域']=='广安门租房',['区域','户型', '面积', '价格']]
iloc 不能直接使用布尔索引, 需要转换成boolean的列表
python">df.iloc[(df['区域']=='广安门租房').to_list(),[0,2,3,4]]
2.3 query查询方法和isin 方法
根据条件来查询数据, 有两种方式
-
布尔索引 df[条件]
-
df.query(‘条件字符串’)
python">query_df= df.query('区域 in ["望京租房","天通苑租房","回龙观租房"]').query('朝向 in ["东","南"]') df.query('区域 in ["望京租房","天通苑租房","回龙观租房"] and 朝向 in ["东","南"]')
使用query方法, 不需要在带上dataframe对象, 直接写条件的字符串 需要注意的是, 如果涉及到条件还有字符串, 单引号双引号闭合的顺序不要写错了
多个条件可以写在一个条件中, 用and连接, 字符串里的多个条件不需要用() 括起来
-
series 的 isin 方法
判断series的值是否在某一范围内, 在传入的列表范围内, 返回True, 不在范围内返回False
python">df[(df['区域'].isin(["望京租房","天通苑租房","回龙观租房"])) &(df['朝向'].isin(["东","南"])) ]
3 DataFrame增 删 改数据
3.1 增加一列数据
直接添加一个新列并赋值, 添加的新列会在最后一列
df[‘新列名’] = 值/[]/series
- 如果赋值的是一个单一的值, 这一列所有的数据取值都相同
python">df['城市'] = '北京'
- 如果赋值的是列表, 列表的长度需要和df和行数一致
python">temp_df = df.head()
temp_df['区县'] = ['朝阳区','朝阳区','西城区','昌平区','朝阳区']
上面的代码会由警告 警告的意思是对temp_df的修改不会影响到df
想没有这个警告, 可以temp_df = df.head().copy()
df.insert(loc=行号, column = 列名 value= 新列值)
python">temp_df.insert(loc=2,column='区县',value=['朝阳区','朝阳区','西城区','昌平区','朝阳区'])
insert方法执行之后, 会直接修改调用这个方法的dataframe数据
3.2 删除一行/一列数据
df.drop(labels = 列名,axis = ,inplace)
-
labels 要删除的一行/一列的名字, 要删除的行/列名的列表
-
axis 按行,按列删除, 很多方法里都有的参数
- 控制当前操作 按行还是按列, 很多计算,删除,修改的操作, 都可以按行,也可以按列, 有这样选择的方法, 都有这个axis 参数
- 求和 可以按行 也可以按列
- 求平均
- 默认值都是0
- 可选的值 0 / 1
- 默认值操作发现有问题, 改成1就可以了
- 控制当前操作 按行还是按列, 很多计算,删除,修改的操作, 都可以按行,也可以按列, 有这样选择的方法, 都有这个axis 参数
-
inplace 默认False 不会在原来的数据上删除,而是在副本上删除
- 改成True 会在当前数据直接删除
3.3 数据去重
df.drop_duplicates()
- subset =
- 默认 所有列值都相同会被认为是重复数据
- 通过subset传入一个列表以后, 列表中的字段, 数据是重复的就会被认为是重复数据,会被删除
- keep
- first 默认 重复的数据保留第一条
- last 最后一个 重复的数据保留最后一条
- False 有重复的都删除
- inplace 通用的修改数据时的参数
python的链式调用说明
找到被删除的数据
python"># 获取删除之后的数据的行索引, 转换成列表
drop_dup_list = df.drop_duplicates().index.to_list()
# 使用所有数据的行索引判断是否在去重之后的索引里, 对这个结果取反( ~ True变成False False变成True)
drop_list = df.index[~df.index.isin(drop_dup_list)] # 获取到被删除的索引
df.loc[drop_list] # 被删除的数据
3.4 数据的修改 直接改/replace方法
找到要修改的数据 , 直接赋值
python">temp_df['户型']='3室1厅'
temp_df.loc[0,'区域'] ='朝阳租房'
temp_df.iloc[2,1]='远见名苑小区'
replace方法
python">temp_df.replace(to_replace='天通苑北1区',value='天通苑北二区',inplace=True)
to_replace 要被替换的旧数据 注意 旧数据传错了,在df里不存在, 方法不会报错, 会执行但没有效果
value 要改成的新的值
inplace 修改数据方法中通用的参数
3.5 apply 通过自定义函数来修改数据
series的apply方法
- 先定义一个方法(函数) 这个方法要有返回值
python">def func(area_str):print('调用了func方法====',area_str)if area_str =='广安门租房':return '西城租房'elif area_str =='天通苑租房':return '昌平租房'else:return area_str
- 通过series.apply(方法对象)
python">temp_df['区域'].apply(func)
pandas 会遍历Series的每一个值, 每遍历一个值就会调用一次func方法, 把这个值作为参数传进来, 并保存结果, 把每次遍历获得的方法返回, 组织成Series对象, 下面是类似的模拟的代码
python"># 准备列表用于接受返回值 result_list = [] # 遍历Series的每一个值 for area_str in temp_df['区域'].to_list(): # 调用写好的方法, 把结果保存到列表中 result_list.append(func(area_str)) # 利用列表创建Series pd.Series(result_list,name='区域')
- 自定义方法, 第一个参数必须用来接收遍历Series的数据, 如果有额外的参数从第二个参数开始
python">def func(area_str,arg1,arg2):print('调用了func方法====',area_str)if area_str =='广安门租房':return arg1elif area_str =='天通苑租房':return arg2else:return area_str
apply调用的时候, 通过args参数传递额外的参数
python">pd.Series(result_list,name='区域')
#%%
temp_df['区域'].apply(func,args=('西城租房','昌平租房'))
dataframe的apply
python">df.apply(func,axis = )
dataframe的apply方法, 会按行/按列 遍历数据, 把一列/一行的数据对应的Series对象传递给自定义函数的第一个参数
axis = 0 默认值, 传的是一列数据
axis= 1 传的是一行数据
举例: 区域是望京租房的改成1室1厅, 区域是天通苑租房的改成3室1厅,
python">def func1(s):if s['区域'] == '望京租房':s['户型']='1室1厅'elif s['区域'] == '天通苑租房':s['户型']='3室1厅'return s
temp_df2.apply(func1,axis=1)def func1(s,arg1,arg2):if s['区域'] == '望京租房':s['户型']=arg1elif s['区域'] == '天通苑租房':s['户型']=arg2return s
temp_df2.apply(func1,axis=1,args=('1室1厅','3室1厅'))
举例: 地址添加小区, 面积除2
python">def func2(s):# print(s)# print('=======',s.name)if s.name=='地址':return s+'小区'elif s.name=='面积':return s/2else:return s
python">temp_df2.apply(func2)
df的applymap方法
遍历dataframe中的每一个值, 可以通过自定义函数来修改这个值, 修改之后的结果就是这个方法的返回值
- 遍历的顺序, 从左到右一列一列遍历, 每一列按照从上到下的顺序
python">temp_df2.apply(func1,axis=1,args=('1室0厅','3室1厅'))
# 值是天通苑租房 改成昌平租房, 值是8000会+500, 其它值不做修改
def func3(value):print(value)print('=======apply map =========')if value=='天通苑租房':return '昌平租房'elif value ==8000:return value+500else:return value
temp_df2.applymap(func3)
4 修改行列索引
修改index
- set_index(列名) 把某一列值设置为索引
- reset_index() 重置索引, 把索引还原为从0开始的rangeIndex
- 都有 inplace 参数
加载数据的时候, 也可以直接指定某一列作为index
python">df = pd.read_csv('C:/Develop/深圳42/data/LJdata.csv',index_col='地址') # index_col=0
整体替换index 和 columns属性
- df.index 和 df.columns 都是 Index类型的对象, 这种对象有共同的特点, 不能修改单个值
- df.index[0] = ‘a’ 这种修改是不支持的
- df.columns[0] = 'address’这种修改是不支持的
- 可以整体替换index 和 columns
python">df.columns = ['address', '区域', '户型', '面积', '价格', '朝向', '更新时间', '看房人数']
rename方法
python">temp_df.rename(index={'a':'A'},columns={'address':'地址'},inplace=True)
index 修改索引 {‘要修改的老的索引’:‘改之后的新索引值’}
columns修改列名 {‘要修改的老的列名’:‘改之后的新列名’}
这个方法和replace 有相同的问题, 老的值不存在的时候不会报错, 代码会执行就是没有效果, 修改之后一定要查看是否修改成功
inplace = 默认False 改成True直接修改原来的数据
若有错误与不足请指出,关注DPT一起进步吧!!!