数据处理与统计分析篇-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
df
和df
拼接
# 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填充.
df
和Series
拼接
# 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
细节:
只能列(水平)拼接
默认是内连接
如果两个df对象关联的字段相同, 可以用: on, 否则用left_on 和 right_on
如果两个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='右表后缀')
细节
只能列(水平)拼接
默认是 左外连接.
如果两个df有重名字段, 需要手动设置后缀名.
默认是根据两个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()
原文地址:https://blog.csdn.net/m0_60916732/article/details/142401701
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!