笔者Python数据分析活用Pandas库学习笔记专栏链接🔗导航:
数据组合主要包括,连接和合并
连接:添加行,添加列
合并多个数据集:一对一合并;多对一合并;多对多合并
"""
2021.02.21
author:alian
数据组合
"""
import pandas as pd
# 先加载几个数据集
df1 = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\concat_1.csv')
df2 = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\concat_2.csv')
df3 = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\concat_3.csv')
# 添加行
row_concat = pd.concat([df1,df2,df3],ignore_index=True)
print(row_concat)
# 添加列
col_concat = pd.concat([df1,df2,df3],axis=1,ignore_index=True)
col_concat['new_col_list'] = ['n1','n2','n3','n4'] # 添加一个新列
col_concat['new_col_list'] = pd.Series['n1','n2','n3','n4'] # 添加一个新列
# 连接具有不同列的行
rows = pd.concat([df1,df2],ignore_index=False,join='inner') # join='inner':保留数据集都有的列
# 连接具有不同行的列
cols = pd.concat([df1,df3],axis=1,join='inner')
# 合并多个数据集
person = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\survey_person.csv')
site= pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\survey_site.csv')
survey= pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\survey_survey.csv')
visited= pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\survey_visited.csv')
# 1)一对一合并
visited_subset = visited.loc[[0,2,6],] # 连接的列不含任何重复值
o2o_merge = site.merge(visited_subset,left_on='name',right_on='site') # left_on,right_on:指定左右数据集匹配的列
# 2)多对一合并
m2o_merge = site.merge(visited,left_on='name',right_on='site') # 以“多”数据集为基准自动复制与之匹配
# 3)多对多合并
# 创建多数据集
ps = person.merge(survey,left_on='ident',right_on='person')
vs = visited.merge(survey,left_on='ident',right_on='taken')
ps_vs = ps.merge(vs,left_on=['ident','taken','quant','reading'],
right_on=['person','ident','quant','reading']) # 匹配列一一对应,若名称存在冲突,pandas会自动添加后缀
在pandas中NaN表示缺失值,缺失值和其他类型的数据不同,实际上它们没有什么意义,缺失值不等于任何值,甚至不等于缺失值。
从numpy库中导入缺失值:
from numpy import NAN,NaN,nan
"""
2021.02.21
author:alian
缺失数据
"""
from numpy import NAN,NaN,nan
import pandas as pd
# 测试是否为缺失值的函数:isnull,notnull
print(pd.isnull(NaN))
print(pd.notnull(NaN))
visited_file = r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\survey_visited.csv'
# 直接加载数据
print(pd.read_csv(visited_file))
# 加载数据,不包含默认缺失值
print(pd.read_csv(visited_file,keep_default_na=False))
# 手动指定缺失值
print(pd.read_csv(visited_file,na_values=[''],keep_default_na=False))
# 重建索引
gapminder = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\gapminder.tsv')
life_exp = gapminder.groupby(['year'])['life'].mean() # 通过分组操作重建索引
print(life_exp)
print(life_exp.loc[range(2000,2010), ])
y2000 = life_exp[life_exp.index>2000] # 取子集
# 调用reindex方法
print(y2000.reindex(range(2000,2010)))
缺失值数量等于数据总行数减去非缺失值的行数
# 查找缺失值
ebola = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\country_timeseries.csv')
# 统计非缺失值的个数
print(ebola.count())
# 用总行数减去非缺失值的行数即得到缺失值的行数
num_rows = ebola.shape[0]
num_missing = num_rows - ebola.count()
利用numpy中的count_nonzero和isnull方法统计数据中缺失值的总数或者特定列中缺失值的个数
import numpy as np
print(np.count_nonzero(ebola.isnull()))
print(np.count_nonzero(ebola['Cases_Guinea'].isnull()))
利用Serise的value_counts方法获取缺失值的个数,dropan参数
print(ebola.Cases_Guinea.value_counts(dropna=False).head())
# 替换
print(ebola.fillna(0).iloc[0:10,0:5]) # 用0替换缺失值
# 前后值填充
print(ebola.fillna(method='ffill').iloc[0:10,0:5])
print(ebola.fillna(method='bfill').iloc[,0:5].tail())
该方法存在一个问题,若缺失值位于最前或最后那么缺失值将继续存在。
pandas中插值的方法默认以线性插值来填充
print(ebola.interpolate().iloc[0:10,0:5])
dropna方法删除缺失值:参数how参数指定行或列的删除条件,两种取值,any(只要包含NA值即删除)与all(全为NA才 删除);thresh参数允许在删除行或列之前 指定非NaN值的数量。
可以忽略缺失值的内置方法有mean和sum,这些参数通常有skipna参数
# 忽略缺失值的计算
print(ebola.Cases_Guinea.sum(skipna=True))
数据整理是指对数据集进行结构化处理,使其易于分析和可视化。它是数据清理的主要目标。整洁数据有助于简化数据分析、可视化和收集工作。
Hadley Wickham指出整洁数据要满足一下3个条件:
每个观测值成一行;每个变量成一列;每种观测单元构成一张表格。
melt函数可以把DataFrame重塑成整洁的数据格式,参数如下:
# 固定一列
pew = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\pew.csv')
pew_long = pd.melt(pew,id_vars='religion',var_name='income',value_name='count')
print(pew_long)
# 固定多列
billboard = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\billboard.csv')
billboard_long = pd.melt(billboard,id_vars=['year','artist','track','time','date.entered'],var_name='week',value_name='rating')
print(billboard_long.head())
# 包含多个变量的列
ebola = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\country_timeseries.csv')
ebola_long = pd.melt(ebola,id_vars=['Date','Day'])
# 单独拆分和添加列(简单方法)
# 获取variable列,访问字符串方法,依据分隔符拆分列
variable_split = ebola_long.variable.str.split('_')
# 把列拆分好之后,拆分结果会保存在一个列表中。
返回的向量的顺序和数据顺序相同
# 在单个步骤中进行拆分和组合(简单方法)
variable_split = ebola_long.variable.str.split('_',expand = True)
variable_split.columns = ['status','country']
ebola_parsed = pd.concat([ebola_long,variable_split],axis=1)
print(ebola_parsed.head())
拆分返回的是包含两个元素的列表,且每个元素都是新列。利用这一点,可以使用内置zip函数把拆分项列表组合在一起。
zip的功能可以理解为:把每个传入的容器堆叠起来,然后以元组的形式逐列返回值。
同样可以使用ebola_long.variable.str.split(‘_’)。不过由于容器是Seriies对象,需要将其拆包,可以使用星号操作符*对容器进行拆包。
# 在单步骤中进行拆分和组合(复杂方法)
ebola_long['status'],ebola_long['country'] = zip(*ebola_long.variable.str.split('_'))
# 列与列中的变量
weather = pd.read_csv(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\weather.csv')
weather_melt = pd.melt(weather,id_vars=['id','year','month','element'],var_name='day',value_name='temp')
weather_tidy = weather_melt.pivot_table(index=['id','year','month','day'],columns='element',values='temp')
weather_tidy_flat = weather_tidy.reset_index()
# 一张表中多个观测单元(归一化)
billboard_songs = billboard_long[['year','artist','track','time']]
billboard_songs = billboard_songs.drop_duplicates() # 删除重复的行
billboard_songs['id'] = range(len(billboard_songs)) # 为每行分配唯一的值
billboard_ratings = billboard_long.merge(billboard_songs,on=['year','artist','track','time']) # 使用新id匹配歌曲的每周排名
billboard_ratings = billboard_ratings[['id','date.entered','week','rating']] # 取想放入的列子集
# 跨多表的观测单元
import os
import urllib
# 只下载前5个数据集
with open(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\raw_data_urls.txt') as data_urls:
for line,url in enumerate(data_urls):
if line ==5:
break
fn = url.split('/')[-1].split()
fp = os.path.join('..','data',fn)
print(url)
print(fp)
urllib.request.urlretrieve(url,fp)
import glob
# 从nyc-taxi数据文件夹获得csv文件列表
nyc_taxi_data = glob.glob(r'D:\Python数据分析\Pandas\pandas_for_everyone-master\data\fhv_*')
# 连接dataframe
taxi1 = pd.read_csv(nyc_taxi_data[0])
taxi2 = pd.read_csv(nyc_taxi_data[1])
taxi3 = pd.read_csv(nyc_taxi_data[2])
taxi4 = pd.read_csv(nyc_taxi_data[3])
taxi5 = pd.read_csv(nyc_taxi_data[4])
taxi = pd.concat([taxi1,taxi2,taxi3,taxi4,taxi5])
# 使用循环加载多个文件
list_taxi_df = []
# 循环遍历每个CSV文件名
for csv_filename in nyc_taxi_data:
# 可以选择输出文件名以便调试
df = pd.read_csv(csv_filename)
list_taxi_df.append(df)
# 连接起来
taxi_loop_concat = pd.concat(list_taxi_df)
# 使用列表推导加载多个文件
list_taxi_df = []
for csv_filename in nyc_taxi_data:
df = pd.read_csv(csv_filename)
list_taxi_df.append(df)
# 使用列表推导式重写
list_taxi_df_comp = [pd.read_csv(data) for data in nyc_taxi_data]
# 将结果连接
list_taxi_concat_comp = pd.concat(list_taxi_df_comp)