pandas的拼接分为两种:
- 级联: pd.concat, pd.append
- 合并: pd.merge, pd.join
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
nd = np.random.randint(0,150,size=(5,4))
nd
# 结果如下:
array([[ 54, 65, 70, 31],
[ 5, 85, 36, 137],
[ 87, 38, 63, 77],
[ 89, 82, 58, 96],
[145, 125, 89, 84]])
# 列级联
np.concatenate([nd,nd], axis=1)
# 结果如下:
array([[ 54, 65, 70, 31, 54, 65, 70, 31],
[ 5, 85, 36, 137, 5, 85, 36, 137],
[ 87, 38, 63, 77, 87, 38, 63, 77],
[ 89, 82, 58, 96, 89, 82, 58, 96],
[145, 125, 89, 84, 145, 125, 89, 84]])
为方便讲解,我们首先定义一个生成DataFrame的函数:
def make_df(cols, index):
data = {col:[str(col)+str(ind) for ind in index] for col in cols}
df = DataFrame(data= data, columns = cols, index = index)
return df
df1 = make_df(['a','b','c'],[1,2,3])
df1
# 结果如下:
df2 = make_df(['a','b','c'],[4,5,6])
df2
# 结果如下:
pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False,
copy=True)
和np.concatenate一样,优先增加行数(默认axis=0)
# np.concatenate(axis=1)的情况是水平级联, np中没有index, 和columns 所以只要行列相等就可以级联
# 在pd中, 如果行 和 列 不一致, 但是shape(形状)相同, 会级联成一个更大的df, 但是不对应的值会填充NaN
pd.concat([df1, df2], axis=1)
# 结果如下:
pd.concat([df1, df2], axis=0)
# 结果如下:
df3 = make_df(['a','b','c'],[2,3,4])
df3
# 结果如下
pd.concat([df1,df3],axis=1)
# 水平合并以后结果如下:
# git中有 .gitignore 这个文件, 会把写入的文件路径给屏蔽, 不会被上传到github
# add . commit push
# ignore_index 作用是对索引重新排序
pd.concat([df1,df3],axis=0, ignore_index=True)
# 在工作中, 大部分的分析数据来源于mysql,mysql中的id都是唯一的, 分表
# mysql在面试中是最重要的,分表 每个表最大的储存限制是100w条, 一般只会使用80W条是最优的
concat([x,y],keys=[‘x’,’y’])
df4 = pd.concat([df1,df3],keys=['期中','期末'])
df4
# 结果如下:
不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
有3种连接方式:
df1
# 结果如下:
df5 = make_df(['c','d','e'],[3,4,5])
df5
# 结果如下:
# concat默认使用的外连接
df6 = pd.concat([df1,df5],axis=0)
df6
# 结果如下:
# 回忆mysql中, outer和inner的不同
# 外连接 left 以左边的表中的数据为核心, 右边数据不匹配,则填充Null
# 内连接 join 两边表数据不完全对应的话, 会只显示能对应上的数据
# join 默认值是outer
df6 = pd.concat([df1,df5],axis=1, join='inner')
df6
# 同mysql一致
df1
# 结果如下:
df5
# 结果如下:
df7 = pd.concat([df1, df5], join_axes=[df1.columns])
df7
# join_axes 的值 是一个列表[df1.index]
# select df1.a, df1.b , df1.c from df1 left join df5 using(c);
# using(c) 相当于: on df1.c=df5.c
由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加
append 和 concat相似
df1
# 结果如下:
df2
# 结果如下:
# 垂直
df1.append(df2)
merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
注意每一列元素的顺序不要求一致
df1
# 结果如下:
df2
# 结果如下:
# 默认是内连接, 表的两边数据都不对应
pd.merge(df1,df2)
# 结果如下
display(df1,df5)
pd.merge(df1,df5, how='right')
# 结果如下:
pd.merge(df1,df5,how='left')
# 结果如下:
df1
# 结果如下:
df8 = make_df(['c','d','e'],[1,1,1,4])
df8
# 结果如下:
pd.merge(df1,df8)
# select * from df1 join df8 on df1.c= df8.c
pd.merge(df1,df8, how='left')
# 结果如下:
pd.merge(df1,df8,how='outer')
# 在工作中用outer , 可以自动分配
pd.merge(df1,df8,how='right')
# 结果如下:
df8
# 结果如下:
df8.iloc[0]['d'] = 'qwe'
df8['e'][4] = 'asd'
df9 = make_df(list('abd'),[1,1,4,4])
df9
# 结果如下;
pd.merge(df9, df8)
# 结果如下:
pd.merge(df9, df8,how='outer')
# 结果如下:
df1
# 结果如下:
# on的作用是将两个表中相同数据类型, 含义一致的字段进行连接的
pd.merge(df1,df10, left_on='c',right_on='w')
# mysql
# select *
df11 = make_df(list('bcd'),[1,2,3])
df11
# 结果如下:
pd.merge(df1,df11,on='b')
# mysql中一般碰到两个字段相同, 但是代表的含义不一样, 或者数据类型不同
# a.u = b.u a.o - b.o
# select a.o a_o, b.o b_o
当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
可以使用suffixes=自己指定后缀
pd.merge(df1,df11,on='c',suffixes=('_up','_down'))
# 结果如下:
United States America
import pandas as pd
from pandas import DataFrame, Series
# 先导入数据文件
# 各州的面积
areas = pd.read_csv('../data/state-areas.csv')
# 缩写
abbr = pd.read_csv('../data/state-abbrevs.csv')
# 人口
pop = pd.read_csv('../data/state-population.csv')
areas.head()
pop.head()
# 结果如下:
# 开始合并
abbrToPop = pd.merge(abbr,pop, left_on='abbreviation', right_on='state/region', how='outer')
abbrToPop.head()
# 合并结果如下:
# 将重复的列删除掉
# .drop()
# 一般的一执行完就打印的, 这种形式的方法不对原数据产生影响, inplace代表是否对原数组产生影响
abbrToPop.drop(columns='abbreviation', inplace=True) # 或者abbrToPop.drop(labels='abbreviation', axis=1)
# 空数据一般会显示NaN
abbrToPop.isnull().any()
# 结果如下:
state True
state/region False
ages False
year False
population True
dtype: bool # 其中返回True的字段中存在NAN空数据, 需要进行处理
# 怎么计算丢失数据的数量
# state population
abbrToPop['state'].isnull().sum()
# 结果如下: 96
# 把空数据填充上, 得到NAN行的筛选条件
cond = abbrToPop['state'].isnull()
# state是州名, 如何填充
# unique()去除重复的值
abbrToPop['state/region'][cond].unique()
# 结果如下:array(['PR', 'USA'], dtype=object)
# 我们通过翻阅资料查到了PR的全称
# Puerto Rico
# 开始赋值
cond_pr = abbrToPop['state/region'] == 'PR'
abbrToPop['state'][cond_pr] = 'Puerto Rico'
cond_usa = abbrToPop['state/region'] == 'USA'
abbrToPop['state'][cond_usa] = 'United States'
abbrToPop.isnull().any()
# 结果如下:
state False
state/region False
ages False
year False
population True
dtype: bool # 成功将state数据修复
abbrToPop.dropna(inplace=True)
# population 查阅资料, 我们先删除掉
abbrToPop.isnull().sum()
# 结果:
state 0
state/region 0
ages 0
year 0
population 0
dtype: int64
# 还有一个表需要合并
areas.head()
# 结果如下
# 融合面积
abbrToPopToAreas = pd.merge(abbrToPop,areas, on='state',how='outer' )
abbrToPopToAreas.head()
abbrToPopToAreas.isnull().sum()
# 结果如下:
state 0
state/region 0
ages 0
year 0
population 0
area (sq. mi) 48
dtype: int64 # area字段有48个空值
cond_area = abbrToPopToAreas['area (sq. mi)'].isnull()
total_area = areas['area (sq. mi)'].sum()
total_area # 结果是: 3790399
# U.S.A
cond_ab = abbrToPopToAreas['state/region'] == 'USA'
abbrToPopToAreas['area (sq. mi)'][cond_ab] = total_area
abbrToPopToAreas.isnull().sum()
# 数据处理完毕后结果:
state 0
state/region 0
ages 0
year 0
population 0
area (sq. mi) 0
dtype: int64
# 现在的表已经完全融合完成了
# 现在可以进行分析了
abbrToPopToAreas_2010 = abbrToPopToAreas.query('year == 2010 & ages == "total"')
abbrToPopToAreas_2010.head()
# 结果如下:
# 工作中会使用id作为列的索引
# set_index()
abbrToPopToAreas_2010.set_index('state', inplace=True)
abbrToPopToAreas_2010.head()
density_2010 = abbrToPopToAreas_2010['population'] / abbrToPopToAreas_2010['area (sq. mi)']
density_2010
# 结果如下:
state
Alabama 91.287603
Alaska 1.087509
Arizona 56.214497
Arkansas 54.948667
California 228.051342
Colorado 48.493718
Connecticut 645.600649
Delaware 460.445752
District of Columbia 8898.897059
Florida 286.597129
Georgia 163.409902
Hawaii 124.746707
Idaho 18.794338
Illinois 221.687472
Indiana 178.197831
Iowa 54.202751
Kansas 34.745266
Kentucky 107.586994
Louisiana 87.676099
Maine 37.509990
Montana 6.736171
Nebraska 23.654153
Nevada 24.448796
New Hampshire 140.799273
New Jersey 1009.253268
New Mexico 16.982737
New York 356.094135
North Carolina 177.617157
North Dakota 9.537565
Ohio 257.549634
Oklahoma 53.778278
Oregon 39.001565
Maryland 466.445797
Massachusetts 621.815538
Michigan 102.015794
Minnesota 61.078373
Mississippi 61.321530
Missouri 86.015622
Pennsylvania 275.966651
Rhode Island 681.339159
South Carolina 144.854594
South Dakota 10.583512
Tennessee 150.825298
Texas 93.987655
Utah 32.677188
Vermont 65.085075
Virginia 187.622273
Washington 94.557817
West Virginia 76.519582
Wisconsin 86.851900
Wyoming 5.768079
Puerto Rico 1058.665149
United States 81.607845
dtype: float64
abbrToPopToAreas_2010['density_2010'] = density_2010
abbrToPopToAreas_2010.head()
# sort_values 根据值来进行排序
abbrToPopToAreas_2010.sort_values(by='density_2010').tail()
import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import numpy as np
apple = pd.read_csv('../data/AAPL.csv')
apple.head()
# 结果如下:
apple.dtypes
# 结果如下:
Date object
Open float64
High float64
Low float64
Close float64
Adj Close float64
Volume float64
dtype: object # 在这里可以看见Date是object类型的
apple['Date'] = pd.to_datetime(apple['Date'])
apple.dtypes
# 结果如下:
Date datetime64[ns]
Open float64
High float64
Low float64
Close float64
Adj Close float64
Volume float64
dtype: object # Date的数据类型转换为datetime64
apple.set_index('Date', inplace=True)
# 结果如下:
adj_plot = apple['Adj Close'].plot()
fig = adj_plot.get_figure()
# set_size_inches 设置图片的大小, 单位是英寸
fig.set_size_inches(12,6)
# 结果如下:
# 因为Volume这一列数据量级太大,不适合分析,故删除
apple.drop('Volume', axis=1, inplace=True)
app = apple.plot()
fig1 = app.get_figure()
fig1.set_size_inches(12,6)