当前位置: 首页 > news >正文

Python笔记 第三方库之Pandas的数据组合与缺失数据处理篇

第二章Pandas③篇!!!

数据组合

1.1 数据清理

1. 在动手进行数据分析工作之前,需要进行数据清理工作

每个观测值成一行

每个变量成一列

每种观测单元构成一张表格

2. 数据整理好之后,可能需要多张表格组合到一起才能进行某些问题的分析

一张表保存公司名称,另一张表保存股票价格

单个数据集也可能会分割成多个,比如时间序列数据,每个日期可能在一个单独的文件中

2.1 连接介绍

1. 组合数据的一种方法是使用“连接”(concatenation)

 连接是指把某行或某列追加到数据中

 数据被分成了多份可以使用连接把数据拼接起来

把计算的结果追加到现有数据集,可以使用连接

2.2 添加行-DataFrame连接

1. 加载多份数据,并连接起来

import pandas as pd# 读取三个CSV文件到DataFrame对象中
# 这里三个DataFrame都从同一个文件读取,实际使用中可能是不同的文件
df1 = pd.read_csv('data/concat_1.csv')
df2 = pd.read_csv('data/concat_1.csv')
df3 = pd.read_csv('data/concat_1.csv')# 打印三个DataFrame的内容到控制台
print(df1)
print(df2)
print(df3)

2. 可以使用concat函数将上面3个DataFrame连接起来

    需将3个DataFrame放到同一个列表中

# 将三个DataFrame按行进行拼接
# 使用pandas的concat函数将df1、df2、df3三个DataFrame在行方向上进行连接
row_concat = pd.concat([df1, df2, df3])# 打印拼接后的结果
print(row_concat)

3. 通过 iloc ,loc等方法取出连接后的数据的子集 

row_concat.iloc[3,]

row_concat.loc[3,]

2.3 添加行-DataFrame和Series连接

1. 使用concat连接DataFrame和Series

# 创建一个新的pandas Series对象,包含四个字符串元素
new_series = pd.Series(['n1', 'n2', 'n3', 'n4'])# 打印输出Series对象的内容
print(new_series)

由于Series是列数据,concat方法默认是添加行,但是Series数据没有行索引, 所以添加了一个新列,缺失的数据用NaN填充

NaN是Python用于表示“缺失值”的方法

2. 如果想将['n1','n2','n3','n4']作为行连接到df1后,可以创建DataFrame并指定列名

# 创建一个新的DataFrame对象,包含一行数据
# 数据内容为['n1', 'n2', 'n3'],列名为['A', 'B', 'C', 'D']
# 注意:数据列数与列名数量不匹配,会导致创建的DataFrame中存在NaN值
new_row_df = pd.DataFrame([['n1', 'n2', 'n3']], columns=['A', 'B', 'C', 'D'])
print(new_row_df)

2.4 添加行-append函数

1. concat可以连接多个对象,如果只需要向现有DataFrame追加一个对象,可以通过append函数来实现 df1.append(new_row_df)


# 将两个DataFrame进行追加操作并打印结果
# 该操作将df2的所有行添加到df1的末尾
print(df1.append(df2))# 将新的行数据追加到df1并打印结果
# new_row_df通常是一个包含新行数据的DataFrame
print(df1.append(new_row_df))

2. 使用Python字典添加数据行

DataFrame中append一个字典的时候,必须传入ignore_index = True

# 创建一个字典,包含键值对数据
data_dict = {'A': 'n1', 'B': 'n2', 'C': 'n3', 'D': 'n4'}# 将字典数据追加到DataFrame中,忽略原始索引并重新生成索引
df1.append(data_dict, ignote_index=True)

2.5 添加行-重置索引

1. 如果是两个或者多个DataFrame连接,可以通过ignore_index = True参数,忽略后面DataFrame的索引

# 将多个DataFrame按行拼接,并忽略原始索引
# 使用pd.concat函数将df1、df2、df3三个DataFrame进行垂直拼接
# ignore_index=True参数表示重新生成连续的整数索引,不保留原始索引
row_concat_ignore_index = pd.concat([df1, df2, df3], ignore_index=True)
print(row_concat_ignore_index)

2.6 添加列-concat函数

1. 使用concat函数添加列,与添加行的方法类似

需要多传一个axis参数 axis的默认值是index 按行添加,传入参数 axis = columns 即可按列添加

# 将三个DataFrame按列进行拼接
# 使用pd.concat函数将df1、df2、df3三个DataFrame沿着列轴(axis=1)方向进行拼接
# 拼接后的结果存储在col_concat变量中,并打印输出
col_concat = pd.concat([df1, df2, df3], axis=1)
print(col_concat)

2. 通过列名获取子集

print(col_concat['A'])

2.7 添加列-通过dataframe['列名'] = ['值']

1. 向DataFrame添加一列,不需要调用函数,通过dataframe['列名'] = ['值'] 即可

# 为DataFrame添加新的列数据
# 将列表['n1', 'n2', 'n3', 'n4']赋值给col_concat DataFrame的'new_col'列
col_concat['new_col'] = ['n1', 'n2', 'n3', 'n4']# 打印输出更新后的DataFrame
print(col_concat)

2.8 添加列-通过dataframe['列名'] = Series对象

1. 通过dataframe['列名'] = Series对象 这种方式添加一列

# 创建一个新的Series对象并赋值给DataFrame的new_col_series列
col_concat['new_col_series'] = pd.Series(['n1', 'n2', 'n3', 'n4'])# 打印输出更新后的DataFrame
print(col_concat)

2.9 添加列-重置索引

1. 按列合并数据之后,可以重置列索引,获得有序索引

# 将三个DataFrame对象进行拼接操作
# 参数说明:
#   [df1, df2, df3] - 需要拼接的DataFrame列表
#   axis = 'colums' - 指定拼接轴为列方向
#   ignore_index=True - 用于在数据操作后重置索引,让索引重新从 0 开始连续编号
# 返回值说明:
#   返回拼接后的DataFrame对象
print(pd.concat([df1, df2, df3], axis = 'colums', lgonre_index=True))

合并多个数据集

3.1 简介

1. 在使用concat连接数据时,涉及到了参数join(join = 'inner',join = 'outer')

2. 数据库中可以依据共有数据把两个或者多个数据表组合起来,即join操作

3. DataFrame 也可以实现类似数据库的join操作

4. Pandas可以通过pd.join命令组合数据,也可以通过pd.merge命令组合数据

5. merge更灵活,如果想依据行索引来合并DataFrame可以考虑使用join函数

3.2 加载数据

1. 从数据库加载数据

import sqllite3
# 连接到SQLite数据库文件
con = sqlite3.connect("data/chinook.db")
# 从数据库中查询tracks表的所有数据并加载到DataFrame中
tracks = pd.read_sql_query("SELECT * from tracks", con)
# 打印显示tracks数据的前5行
print(tracks.head())

2. read_sql_query函数

从数据库中读取表,第一个参数是表名,第二个参数是数据库连接对象


# 从数据库中读取所有音乐流派信息并打印显示
# 该代码块执行以下操作:
# 1. 使用SQL查询从genres表中获取所有记录
# 2. 将查询结果存储在pandas DataFrame中
# 3. 打印显示查询到的流派数据
genres = pd.read_sql_query("SELECT * from genres", con)
print(genres)

3.3 一对一合并

最简单的合并只涉及两个DataFrame——把一列与另一列连接,且要连接的列不含任何重复值

1. 先从tracks中提取部分数据,使其不含重复的'GenreId’值

# 从tracks数据集中选择指定索引的行,创建子集并打印输出
# 该代码块实现了数据子集的选择和展示功能
tracks_subset = tracks.loc[[0, 62, 76, 98, 110, 193, 204, 281, 322, 359],]
print(tracks_subset)

2. 通过'GenreId'列合并数据,how参数指定连接方式

how = ’left‘ 对应SQL中的 left outer 保留左侧表中的所有key

how = ’right‘ 对应SQL中的 right outer 保留右侧表中的所有key

how = 'outer' 对应SQL中的 full outer 保留左右两侧侧表中的所有key

how = 'inner' 对应SQL中的 inner 只保留左右两侧都有的key

3. Left 

# 将音乐流派信息与音轨信息进行关联合并
# 通过GenreId字段将genres数据框与tracks_subset数据框进行左连接
# 合并后的数据包含流派信息以及对应的音轨ID、流派ID和播放时长信息
genre_track = genres.merge(tracks_subset[['TrackId', 'GenreId', 'Milliseconds']],
on='GenreId', how='left')
print(genre_track)

4. right

# 将genres数据框与tracks_subset数据框进行合并操作
# 通过GenreId字段进行右连接,保留tracks_subset中的所有记录
# 合并后的数据框包含TrackId、GenreId、Milliseconds和genre相关信息
genre_track = genres.merge(tracks_subset[['TrackId', 'GenreId', 'Milliseconds']],
on='GenreId', how='right')
print(genre_track)

3.4 多对一合并

1. 使用tracks的全部数据

# 将genres数据框与tracks数据框进行左连接合并
# 通过GenreId字段关联两个数据框
# 保留tracks中的TrackId、GenreId和Milliseconds字段
genre_tracks = genres.merge(tracks[['TrackId', 'GenreId', 'Milliseconds']],
on='GenreId', how='left')# 打印合并后的结果
print(genre_track)

2. 转换时间单位 如上面结果所示,Name的值在合并后的数据中被复制了

计算每种类型音乐的平均时长

to_timedelta 将Milliseconds列转变为timedelta数据类型

参数unit='ms' 时间单位 dt.floor('s') dt.floor() 时间类型数据,按指定单位截断数据

# 计算每个音乐流派的平均播放时长并进行格式化处理
# 
# 该代码块执行以下操作:
# 1. 按音乐流派名称分组,计算每首歌曲的平均播放时长(毫秒)
# 2. 将平均时长转换为时间格式,向下取整到秒级别,并按时间长短排序
#
# 返回值:
#   pandas.Series: 索引为音乐流派名称,值为格式化后的时间对象,按时间升序排列genre_time = genre_track.groupby('Name')['Milliseconds'].mean()
pd.to_timedelta(genre_time, unit='ms').dt.floor('s').sort_values()

3. 计算每名用户的平均消费

从三张表中获取数据,用户表获取用户id,姓名

发票表,获取发票id,用户id

发票详情表,获取发票id,单价,数量

# 从数据库中读取客户信息,包含客户ID、名字和姓氏
cust = pd.read_sql_query("SELECT CustomerId,FirstName,LastName from customers",con)# 从数据库中读取发票信息,包含发票ID和对应的客户ID
invoice = pd.read_sql_query('SELECT InvoiceId,CustomerId from invoices',con)# 从数据库中读取发票项目信息,包含发票ID、单价和数量
ii = pd.read_sql_query('SELECT InvoiceId,UnitPrice,Quantity from invoice_items',con)

3.5 join合并

使用join合并,可以是依据两个DataFrame的行索引, 或者一个DataFrame的行索引另一个DataFrame的列索引进行数据合并

1. 加载数据

stocks_2016 = pd.read_csv('data/stocks_2016.csv')
stocks_2017 = pd.read_csv('data/stocks_2017.csv')
stocks_2018 = pd.read_csv('data/stocks_2018.csv')

2. 依据两个DataFrame的行索引

如果合并的两个数据有相同的列名,需要通过lsuffix,和rsuffix,指定合并后的列名的后缀

stocks_2016.join(stocks_2017, lsuffix='_2016', rsuffix='_2017', how='outer’)

3. 将两个DataFrame的Symbol设置为行索引,再次join数据

stocks_2016.set_index('Symbol').join(stocks_2018.set_index('Symbol'),
lsuffix='_2016', rsuffix='_2018’)

4. 将一个DataFrame的Symbol列设置为行索引,与另一个DataFrame的Symbol列进行join

stocks_2016.join(stocks_2018.set_index('Symbol'),lsuffix='_2016',
rsuffix='_2018',on='Symbol')

缺失数据处理

介绍

1. 好多数据集都含缺失数据。缺失数据有多重表现形式

数据库中,缺失数据表示为NULL

在某些编程语言中用NA表示

缺失值也可能是空字符串(’ ’)或数值 在Pandas中使用NaN表示缺失值

1.2 NaN简介

Pandas中的NaN值来自NumPy库,NumPy中缺失值有几种表示形式:NaN,NAN,nan,他们都一样 缺失值和其它类型的数据不同,它毫无意义,NaN不等于0,也不等于空串,

1. 查看NaN,NAN,nan

from numpy import NaN.NAN,nan
print(NaN==True)
print(NaN==False)
print(NaN==0)
print(NaN=='')

加载缺失值

2.1 缺失值来源

1. 缺失值的来源有两个

原始数据包含缺失值

数据整理过程中产生缺失值

2.2 加载包含缺失的数据

1. 加载数据时可以通过keep_default_na 与 na_values 指定加载数据时的缺失值

pd.read_csv('data/survey_visited.csv')

2. 加载数据,不包含默认缺失值

pd.read_csv('data/survey_visited.csv',keep_default_na = False)

3. 加载数据,手动指定缺失值

pd.read_csv('data/survey_visited.csv',na_values=[""],keep_default_na = False)

处理缺失值

3.1 加载数据

train=pd.read_csv('data/titanic_train.csv')test=pd.read_csv('data/titanic_test.csv')print(train.shape)print(train.head())


3.2 字段说明

3.3 查看数据

1. 查看是否获救数据

train['Survived'].value_counts()

2. 检测数据集中每一列中缺失值的百分比

定义missing_values_table,计算每列缺失百分比

查看训练集缺失情况

# 调用missing_values_table函数计算训练数据集中的缺失值信息
train_missing = missing_values_table(train)# 打印训练数据集的缺失值统计结果
print(train_missing)

查看测试集缺失情况

# 调用missing_values_table函数处理test数据集,检测并统计缺失值信息
test_missing = missing_values_table(test)# 打印缺失值统计结果
print(test_missing)

训练集和测试集的缺失值比例基本相似

3.4 缺失值可视化

1.  导入模块import missingno as msno

2. 条形图

import missingno as msno# 生成训练数据缺失值分布的条形图
# 该代码使用missingno库的bar函数可视化数据集中各特征的缺失值情况
# 参数: train - 包含训练数据的DataFrame,其中可能包含缺失值
# 返回值: 返回一个matplotlib图表对象,显示各列缺失值的比例
print(msno.bar(train))

条形图提供了数据集完整性的可视化图形。

我们可以看到“年龄”,“客舱号码”和“登船的港口”列包含值缺失

3.5 查看缺失值之间相关性

3.  数据缺失原因 通过计算缺失值间相关性判断缺失原因

msno.heatmap(train)

3.6 删除缺失值

1.  删除缺失值

删除缺失值会损失信息,并不推荐删除,当缺失数据占比较低的时候,可以尝试使用删除缺失值

2. 按行删除:删除包含缺失值的记录

train_1 = train.copy()    复制一份数据

train_1.dropna(subset=['Age'],how='any',inplace=True)

train_1['Age'].isnull().sum()

train_1.shape

3. 按列删除

当一列包含了很多缺失值的时候(比如超过80%),可以将该列删除,但最好不要删除数据

train_1.drop(['Age'],axis = 1).head()

3.7 填充缺失值

填充缺失值是指用一个估算的值来去替代缺失数

1. 非时间序列数据 使用常量来替换(默认值)

train_constant = train.copy()

train_constant.fillna(0,inplace = True)

train_constant.isnull().sum()

train_constant[train_constant['Cabin']==0].shape

2. 非时间序列数据

使用统计量替换(缺失值所处列的平均值、中位数、众数)

train_mean = train.copy()

train_mean['Age'].fillna(train_mean['Age'].mean(),inplace = True)

train_mean.isnull().sum()

3. 时间序列数据介绍

我们同样可以使用pandas的fillna来处理这类情况

用时间序列中空值的上一个非空值填充

用时间序列中空值的下一个非空值填充

线性插值方法

4. 时间序列数据

加载时间序列数据,数据集为印度城市空气质量数据(2015-2020)

city_day = pd.read_csv('data/city_day.csv',parse_dates=['Date'],index_col='Date')

city_day1=city_day.copy()

city_day.head()

用之前封装的方法,查看数据缺失情况

city_day_missing= missing_values_table(city_day)

city_day_missing

时间序列数据 数据中有很多缺失值,比如Xylene(二甲苯)和 PM10 有超过50%的缺失值 查看包含缺失数据的部分 city_day['Xylene'][50:64]

5. 时间序列数据

数据中有很多缺失值,比如Xylene(二甲苯)和 PM10 有超过50%的缺失值

查看包含缺失数据的部分

city_day['Xylene'][50:64]

6. 时间序列数据

使用ffill 填充,用时间序列中空值的上一个非空值填充

NaN值的前一个非空值是0.81,可以看到所有的NaN都被填充为0.81 city_day.fillna(method='ffill',inplace=True)

city_day['Xylene'][50:65]

7. 时间序列数据

使用bfill填充,用时间序列中空值的下一个非空值填充

NaN值的后一个非空值是209,可以看到所有的NaN都被填充为209

city_day.fillna(method='bfill',inplace=True)

city_day['AQI'][20:30]

8.时间序列数据

线性插值方法填充缺失值

时间序列数据,数据随着时间的变化可能会较大。

使用bfill和ffill进行插补并不是解决缺失值问题的最优方案。

线性插值法是一种插补缺失值技术,它假定数据点之间存在线性关系。 

利用相邻数据点中的非缺失值来计算缺失数据点的值。 

9. 时间序列数据

线性插值方法填充缺失值

city_day1.interpolate(limit_direction="both",inplace=True)

city_day1['Xylene'][50:65]

10. 其它填充缺失值的方法

除了上面介绍的填充缺失值的方法外,还可以使用机器学习算法预测来进行缺失值填充

后续再介绍用算法来填充缺失值的方法

http://www.dtcms.com/a/342373.html

相关文章:

  • 通信工程学习:什么是Camera Calibration相机标定
  • 1000qps怎么保证系统的高可用
  • abc Reachable Set
  • 基于Nodejs作为服务端,React作为前端框架,axios作为通讯框架,实现滑块验证
  • C++ 学习与 CLion 使用:(四)常量和变量,包括字面常量和符号常量
  • 计算机视觉--opencv(代码详细教程)(三)--图像形态学
  • 【框架篇二】FastAPI路由与请求处理
  • javaweb开发笔记——微头条项目开发
  • 零性能妥协:Gearbox Entertainment 通过 AWS 和 Perforce 实现远程开发革命
  • AWS EC2 实例优化检测工具:完整指南与实践
  • WSL的Ubuntu如何改名字
  • AWS Lambda 高并发场景下的错误处理与监控最佳实践
  • 06高级语言逻辑结构到汇编语言之逻辑结构转换 for (...; ...; ...)
  • 一款更适合 SpringBoot 的API文档新选择(Spring Boot 应用 API 文档)
  • 数据结构:构建一棵AVL树需要多少节点(Height VS Nodes in AVL Trees)
  • Claude Code 已支持【团队版】和【企业版】订阅
  • 解析 C 语言整数类型:超越命名的长度奥秘
  • SWMM排水管网水力、水质建模及海绵城市与水环境中的应用
  • 7. if 条件语句的知识与实践
  • 三层交换机
  • CMake2: CMakeLists.txt的常用命令
  • 5.6 element ui
  • 计算机网络技术-第六章
  • STM32 TIM_CtrlPWMOutputs函数
  • 两种单例模式
  • 分享一个免费开源的网站跟踪分析工具Open-Web-Analytics(和GoogleAnalytics一样)
  • 3D 环形旋转图片轮播(纯html,css,js)
  • Docker:安装配置
  • Unity编辑器相关
  • 类加载问题与内存泄漏排查:隐藏在元数据区的致命陷阱