数据处理与统计分析篇-day07-Pandas数据拼接与空值处理

一. 数据组合

连接方式:

inner: 内连接(交集)

left: 左外(左表全集 + 交集)

right: 右外(右表全集 + 交集)

outer: 满外连接(左表全集 + 右表全集 + 交集)

导包

import numpy as np
import pandas as pd
import os
import sqlite3
​
os.chdir(r'D:\CodeProject\03data_processing_analysis\teacher_project')  # 改变当前的工作目录.  change current work directory

concat()

介绍

concat()函数既能实现行拼接(默认), 也能实现列拼接.

行拼接参考: 列名, 列拼接参考: 索引列(行索引)

格式: pd.concat([df1, df2, ...], ignore=是否重置索引, axis=行/列)

默认: 满外连接, 即: 两个df的全集 + 交集

加载数据

df1 = pd.read_csv('data/concat_1.csv')
df2 = pd.read_csv('data/concat_2.csv')
df3  = pd.read_csv('data/concat_3.csv')
df1
df2
df3

dfdf拼接

# 1. 演示行拼接
pd.concat([df1, df2, df3])                  # 默认是: 行拼接.
pd.concat([df1, df2, df3], axis='rows')     # 效果同上
pd.concat([df1, df2, df3], axis=0)          # 效果同上, 0 => rows, 行,   1 => columns, 列
​
# 2. 演示列拼接
pd.concat([df1, df2, df3], axis='columns')  # 列拼接
pd.concat([df1, df2, df3], axis=1)          # 效果同上
​
# 3. 演示 行, 列拼接时, 重置: 索引 和 列名
# 细节: 无论是行, 列拼接时, 只要忽略索引了, 都会默认用 0 ~ n来填充.
pd.concat([df1, df2, df3], axis='rows', ignore_index=True)     # 行拼接
pd.concat([df1, df2, df3], axis='columns', ignore_index=True)     # 列拼接
​
# 4. 验证 行拼接时, 参考: 列名
df4 = pd.DataFrame(['n1', 'n2', 'n3'], columns=['B'], index=['a', 1, 'c'])
df4
​
# 5. 拼接 df1 和 df4
# 行拼接, 参考: 列名
pd.concat([df1, df4], axis='rows')      # 未匹配, 用NAN填充.
​
# 列拼接, 参考: 索引列
pd.concat([df1, df4], axis='columns')   # 未匹配, 用NAN填充.

dfSeries拼接

# 1. 创建Series对象.
s1 = pd.Series(['n1', 'n2', 'n3'])      
s1  # Series对象代表一列数据, 他没有类似于df的列名, 所以 行拼接时, 类似于: 新增了1列 
​
# 2. 使用concat拼接df和series对象.
pd.concat([df1, s1], axis='rows')        # 默认是: 行拼接.
pd.concat([df1, s1], axis='columns')     # 默认是: 列拼接.
​
# 3. 细节, 关于append()函数, 旧版本的Anaconda(例如: Anaconda2020)支持, 新版本中已经被移除掉了, 它能实现的事儿, 用concat()都能做. 
# df1.append(df2)     # 报错
pd.concat([df1, df2]) # 可以平替上述的功能

df新增1列

# 方式1: df对象[列名] = 列表, 要求: 列表的长度 要和 df的行数一致.
# df1['new_col1'] = [10, 20, 30]          # 报错
# df1['new_col'] = [10, 20, 30, 40, 50]   # 报错
df1['new_col1'] = [10, 20, 30, 40]        # 正确
df1
​
# 上述的代码, 加入 concat()
df5 = pd.concat([df1, df2], axis=1)       # 列拼接
df5['new_col1'] = [10, 20, 30, 40]
df5
​
# 方式2: df对象[列名] = Series对象, Series对象值的个数无要求.
df1['new_col2'] = pd.Series([1, 2, 3])
df1['new_col3'] = pd.Series([1, 2, 3, 4])
df1['new_col4'] = pd.Series([1, 2, 3, 4, 5])
df1

merge()

介绍

格式:

df.merge(df2, on='关联字段', how='连接方式', suffixes=(左表后缀, 右表后缀))

参数:

参1: 要被合并的df对象.

参2: on表示两个df合并的 关联字段, 如果一样可以直接写 on, 如果不一样, 则要写 left_on='左表字段名', right_on='右表字段名'

参3: how表示合并方式, 内连接: inner(默认), 左连接: left, 右连接: right, 全(满)连接: outer

细节:

  1. 只能列(水平)拼接

  2. 默认是内连接

  3. 如果两个df对象关联的字段相同, 可以用: on, 否则用left_on 和 right_on

  4. 如果两个df有重名字段, 可以通过 suffixes 设置 左表后缀, 右表后缀

加载数据

# 1. 创建连接对象, 关联: *.db文件.
conn = sqlite3.connect('data/chinook.db')
​
# 2. 从上述的文件中, 读取 歌曲表的信息.
# 参1: 要执行的SQL语句,   参2: 连接对象.
tracks_df = pd.read_sql_query('select * from tracks;', conn)
tracks_df.head()
​
# 3. 从上述的文件中, 读取 歌曲分类表的信息.
genres_df = pd.read_sql_query('select * from genres;', conn)
genres_df

一对一

# 1. 查看 歌曲风格表的信息
genres_df
​
# 2. 查看 歌曲表的信息, 并从中找到 不同的音乐风格的数据.
tracks_subset_df = tracks_df.loc[[0, 62, 76, 98, 110, 193, 204, 281]]
# 获取tracks_df的子集(指定列)
tracks_subset_df[['TrackId', 'GenreId', 'Milliseconds']]        # 歌曲id, 风格id, 歌曲时长(毫秒)
​
# 3. 合并上述两个表, 以 风格 为标准, 合并.
内连接
genres_df.merge(tracks_subset_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId', how='inner')
左外连接
genres_df.merge(tracks_subset_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId', how='left')
右外连接
genres_df.merge(tracks_subset_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId', how='right')
满外连接
# 满外连接, 也叫: 全连接
# 即: 它的查询结果 = 左连接 + 右连接,   即: 左表全集 + 右表全集 + 交集.
genres_df.merge(tracks_subset_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId', how='outer')
参考默认连接
genres_df.merge(tracks_subset_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId')     # 默认是: 内连接 => inner
重名列
# 如果关联的多个df有重名的列, 则默认会加上 _x, _y这样的后缀, 来源于: suffixes字段.
genres_df.merge(tracks_subset_df[['TrackId', 'Name', 'GenreId', 'Milliseconds']], on='GenreId')     # 默认后缀: _x, _y
genres_df.merge(tracks_subset_df[['TrackId', 'Name', 'GenreId', 'Milliseconds']], on='GenreId', suffixes=('_left', '_right'))     # 默认后缀: _x, _y

一对多

# 1. 合并 genres(风格表) 和 tracks(歌曲表)
genres_df.merge(tracks_df[['TrackId', 'Name', 'GenreId', 'Milliseconds']], on='GenreId') 
​
# 需求2: 计算每种类型音乐的平均时长. 
# 1. 合并 genres(风格表) 和 tracks(歌曲表).  交集.
genre_track =  genres_df.merge(tracks_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId', how='inner')    # 风格表.merge(歌曲表['歌曲id', '风格id', '歌曲时长毫秒']) 
# 左外连接.
genre_track =  genres_df.merge(tracks_df[['TrackId', 'GenreId', 'Milliseconds']], on='GenreId', how='left')    # 风格表.merge(歌曲表['歌曲id', '风格id', '歌曲时长毫秒']) 
genre_track
​
# 2. 根据 风格id分组, 计算 时长的平均值.
genre_time = genre_track.groupby(['GenreId', 'Name']).Milliseconds.mean()
genre_time
​
# 3. 扩展, 后边详解.  把上述的 genre_time => 秒.
pd.to_timedelta(genre_time, unit='ms').dt.floor('s')
​
# pd.to_timedelta(genre_time, unit='ms') 意思是: 把 genre_time 的毫秒数, 转换成 pandas.Timedelta 类型.
# dt.floor('s') 意思是: 取整, 取秒.
pd.to_timedelta(genre_time, unit='ms').dt.floor('s').sort_values()

join()-了解

介绍

格式:

df1.join(df2, on='关联字段', how='连接方式', lsuffix='左表后缀', rsuffix='右表后缀')

细节

  1. 只能列(水平)拼接

  2. 默认是 左外连接.

  3. 如果两个df有重名字段, 需要手动设置后缀名.

  4. 默认是根据两个df的 索引列来合并的, 如果想要关联普通列, 需要通过 on 参数实现.

代码演示

# 1. 加载数据, 获取df对象.
stock_2016 = pd.read_csv('data/stocks_2016.csv')
stock_2017 = pd.read_csv('data/stocks_2017.csv')
stock_2018 = pd.read_csv('data/stocks_2018.csv')
stock_2016
stock_2017
stock_2018
​
# 2. 默认情况下, join会参考 两个df的 索引列 进行合并连接.
stock_2016.join(stock_2017, lsuffix='_2016', rsuffix='_2017')               # 默认: 左外连接
stock_2016.join(stock_2017, lsuffix='_2016', rsuffix='_2017', how='left')   # 效果同上
​
# 3. 设置两个df对象的 Symbol列为索引列, 再次关联.
stock_2016.set_index('Symbol')
stock_2017.set_index('Symbol')
​
# 设置索引列, 并关联. 
stock_2016.set_index('Symbol').join(stock_2017.set_index('Symbol'), lsuffix='_2016', rsuffix='_2017', how='left')   # 左外连接
stock_2016.set_index('Symbol').join(stock_2017.set_index('Symbol'), lsuffix='_2016', rsuffix='_2017', how='right')  # 右外连接
stock_2016.set_index('Symbol').join(stock_2017.set_index('Symbol'), lsuffix='_2016', rsuffix='_2017', how='outer')  # 满外连接
stock_2016.set_index('Symbol').join(stock_2017.set_index('Symbol'), lsuffix='_2016', rsuffix='_2017', how='inner')  # 内连接
​
# 4. 设置stock_2016的索引为: Symbol 和 stock_2018做关联.
stock_2016
stock_2018.set_index('Symbol')
​
# 拿着 stock_2016的 指定列(普通列) 和 stock_2018的 索引列 进行关联.
# 细节: on参数设定的是 函数外 df对象的 普通列
stock_2016.join(stock_2018.set_index('Symbol'), lsuffix='_left', rsuffix='_right', on='Symbol', how='outer')

二. 空值处理

在Pandas中, 缺失值来源于numpy包的NAN, nan, NaN, 他们都表示空.

导包

import numpy as np
import pandas as pd
import os
import missingno as msno
​
os.chdir(r'D:\CodeProject\03data_processing_analysis\teacher_project')  # 改变当前的工作目录.  change current work directory

缺失值查看和比较

# 1. 空值比较.
print(np.NAN == True)   # False
print(np.NAN == False)  # False
print(np.NAN == '') # False
print(np.NAN == 0)  # False
​
# 2. 空和空比较, 也都是False.
print(np.NAN == np.nan) # False
print(np.NAN == np.NaN) # False
print(np.nan == np.NaN) # False
​
# 3. 判断是否为空.  Pandas库的 isnull(), isna(),  notnull(), notna()
print(pd.isnull(np.NAN))    # True
print(pd.isnull(''))        # False
​
print(pd.notnull(np.NAN))    # False
print(pd.notnull(''))        # True

加载时操作缺失值

# 1. 读取数据, 获取df对象.
pd.read_csv('data/survey_visited.csv')      # 默认: 会加载缺失值.
​
# keep_default_na: 设置加载时是否加载缺失值.  True(默认): 加载.  False: 不加载.
pd.read_csv('data/survey_visited.csv', keep_default_na=False)
​
# na_values: 设置加载时, 哪些值 设置为缺失值.
pd.read_csv('data/survey_visited.csv', na_values=['734', '751', 'MSK-4', '1939-01-07'])

演示: 删除和填充缺失值

加载数据

# 1. 加载数据, 获取df对象.
train = pd.read_csv('data/titanic_train.csv')
train
​
# 2. 查看数据的常用 统计值.
train.shape         # (891, 12), 行列数
train.info()        # 基本信息
train.describe()    # 统计信息.
​
# 3. 报表的形式, 查看缺失值. 
msno.bar(train)     # 柱状图
msno.heatmap(train) # 查看缺失值之间的关联性. 

删除缺失值

方式1: 按列删除
# 1. 查看 df 对象
train.isnull().sum()        # 查看各列的空值情况.
train.shape                 # (891, 12)
​
# 2. 删除缺失值.
# 按 行 删除缺失值.
train.dropna()
train.dropna(axis='rows')   # 效果同上, 默认按照: 行 删除空值.
train.dropna(axis=0)        # 效果同上, 默认按照: 行 删除空值.
​
# 按 列 删除缺失值
train.dropna(axis='columns')    # 按列删除缺失值.
train.dropna(axis=1).isnull().sum()            # 效果同上.
方式2: subset参数
# subset参数: 参考的列, 即: 该列值为空, 才会删除行, 或者 列.
# how参数: 删除方式, any: 只要有空值, 就删除行或者列. all: 全部为空, 才删除行或者列.
train.dropna(subset=['Age', 'Embarked'], how='all')     
train.dropna(subset=['Age', 'Embarked'], how='any')     
​
# 查看删除后的数据
train.dropna(subset=['Age', 'Embarked'], how='any').isnull().sum()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145001.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【算法题】139. 单词拆分-力扣(LeetCode)

【算法题】139. 单词拆分-力扣(LeetCode) 1.题目 下方是力扣官方题目的地址 139. 单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意:不要求字典中出现的单词全部都使用,并且…

如何下载旧版本app或者旧版本的电脑软件?下载旧版本手机app和电脑软件的方法

下载旧版本软件的方法介绍,下面以下载旧版本剪映为例:

【STM32 Blue Pill编程实例】-手机通过HC-05串口蓝牙控制LED

手机通过HC-05串口蓝牙控制LED 文章目录 手机通过HC-05串口蓝牙控制LED1、HC-05串口蓝牙模块介绍2、硬件准备和接线3、模块配置4、代码实现5、手机控制在本文中,我们介绍如何使用 STM32CubeIDE 和 HAL 库将 HC-05 蓝牙模块与 STM32 Blue Pill 开发板连接。 我们将使用 Android…

分布式事务一致性:本地消息表设计与实践

概念 本地消息表是一种常见的解决分布式事务问题的方法。其核心思想是将分布式事务拆分成本地事务来处理,通过消息队列来保证各个本地事务的最终一致性。 实现步骤 创建本地消息表:在数据库中创建一个本地消息表,用于存储待发送的消息以及消…

泽众P-One性能测试平台火焰图帮助定位产品性能问题

在软件开发过程中,性能问题往往是最头疼的问题之一。随着软件系统的日益复杂,快速准确地定位并解决性能问题变得尤为重要。泽众P-One作为一站式性能测试平台,通过引入火焰图性能分析可视化工具,极大地提升了性能问题的定位效率和解…

PDF样本册如何分享到朋友圈

​想象一下,你刚刚参加了一场行业盛会,获取了一份包含最新行业动态、优秀案例的PDF样本册。你迫不及待地想要分享给身边的朋友,与他们共同学习、探讨。然而,传统的分享方式要么依赖纸质版,要么通过电子邮件&#xff0c…

数据库-约束与多表查询

1.约束 例子: 外键约束 例子: 2.多表查询 多表关系 概述 内连接 外连接 自连接 联合查询 子查询 介绍 标量子查询 仅有一个值 列子查询 行子查询 表子查询 练习

大模型团队招人(校招):阿里巴巴智能信息,2025届春招来了!

阿里巴巴智能信息,2025届春招开始啦,欢迎有意向的优秀同学扫码投递。实习的内容也是大语言模型的核心方向Alignment,在这里有丰富的实验资源、良好的数据支持、优秀的师兄师姐带领你进入大模型的全新领域。内推直达:https://talen…

有哪些软件具备员工电脑的通讯软件管控功能

1、金刚钻信息网站桌面管理系统:系统里集合了上网行为管理、网络传输控制、硬件设备控制等功能,其中网络传输控制功能可以通过控制QQ、微信等 IM工具传输来管控网页和邮件敏感内容发布等渠道,预防企业内部敏感信息外泄。 2、洞察眼MIT系…

Blender软件三大渲染器Eevee、Cycles、Workbench对比解析

Blender 是一款强大的开源3D制作平台,提供了从建模、雕刻、动画到渲染、后期制作的一整套工具,广泛应用于电影、游戏、建筑、艺术等领域。 渲染101云渲染云渲6666 相比于其他平台,如 Autodesk Maya、3ds Max 或 Cinema 4D,Blende…

【JAVA开源】基于Vue和SpringBoot的蜗牛兼职平台

本文项目编号 T 034 ,文末自助获取源码 \color{red}{T034,文末自助获取源码} T034,文末自助获取源码 目录 一、系统介绍1.1 平台架构1.2 管理后台1.3 用户网页端1.4 技术特点 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景…

PHP限定post提交数据的次数

PHP限定post提交数据的次数。 在PHP中&#xff0c;你可以通过记录IP地址的提交次数并在会话或数据库中存储这些信息来实现这个需求。以下是一个简单的PHP示例&#xff0c;它使用会话来跟踪IP地址的提交次数。 <?php session_start(); // 获取用户的IP地址 $ip_address $…

linux内核 devtmpfs介绍

文章目录 概要整体架构流程技术细节 概要 提示&#xff1a;这里可以添加技术概要 linux内核中 devtmpfs实现介绍 内核版本&#xff1a;5.10 Devtmpfs在Linux中是一个特殊的设备文件系统&#xff0c;主要用来linux内核中加速启动过程和管理设备节点。高版本的linux基本都是使用…

使用adb命令进行内存测试

使用 adb &#xff08;Android Debug Bridge&#xff09;&#xff0c;可以从命令行进行多种内存测试和查看内存使用情况。以下是一些常用的 adb 命令可以进行内存测试和分析。 1、获取系统整体内存信息 adb shell dumpsys meminfo 2、获取特定应用内存信息 adb shell dumps…

本地搭建我的世界服务器(JAVA)简单记录

网上参考教程挺多的&#xff0c;踩了不少坑&#xff0c;简单记录一下&#xff0c;我做的是一个私人服务器&#xff0c;就是和朋友3、4个人玩。 笨蛋 MC 开服教程 先放一个比较系统和完整的教程&#xff0c;萌新可用&#xff0c;这个教程很详细&#xff0c;我只是记录一下自己的…

WebServer:log

超时锁的编写 这个问题处于blockqueue.h文件中&#xff0c;内容如下&#xff1a; template<class T> bool BlockDeque<T>::pop(T& item, int timeout) {std::unique_lock<std::mutex> locker(mtx_);while(deq_.empty()) {if(condConsumer_.wait_for(lo…

分享每天开发100个WhatsApp客户方法

获取WhatsApp账号的方式有很多&#xff0c;因为WhatsApp跟微信差不多&#xff0c;可以说是国际版的微信&#xff0c;很多电话就是WhatsApp。所以说收集WhatsApp基本上就跟收集收集号码的方式大同小异&#xff0c;谷歌开发客户是做外贸的基本功之一了&#xff0c;要会谷歌开发客…

百元头戴式蓝牙耳机哪个牌子好?四大优质百元机型推荐

在寻找性价比高的百元头戴式蓝牙耳机时&#xff0c;消费者往往面临众多品牌和型号的选择&#xff0c;市场上的竞争异常激烈&#xff0c;不同品牌推出的产品在功能、音质、舒适度以及续航能力等方面各有千秋&#xff0c;那么百元头戴式蓝牙耳机哪个牌子好&#xff1f;对于那些不…

C++STL的Stack的使用:STL栈和队列的使用介绍、leecode---最小栈、nowcoder---栈的压入、弹出序列等的介绍

文章目录 前言一、STL栈和队列的使用二、leetcode---最小栈三、nowcoder---栈的压入、弹出序列总结 前言 CSTL的Stack的使用&#xff1a;STL栈和队列的使用介绍、leecode—最小栈、nowcoder—栈的压入、弹出序列等的介绍 一、STL栈和队列的使用 #include <iostream> #in…

idea插件之google-java-format

google-java-format插件可用于重新格式化 Java 源代码 统一代码格式 不同的人提交的代码格式化不一样将导致 merge 代码造成大概率冲突&#xff0c;而统一的代码风格无论对项目的可维护性&#xff0c;还是降低 merge 冲突都极为重要。 广泛使用的两种 Java 代码规范&#xf…