希望自己在兵荒马乱中保持韧性,发现宝藏。
目录
1.清除重复行或某个字段:drop_duplicates函数
2.apply函数
3.axis的理解
4.pd.read_csv()读数据
5.stack()和unstack()函数
6.groupby函数的使用
7.数据索引
8.数据排序
9.计算某列有多少个不同的值,类似sql中count(distinct A)
10.数据筛选,类似sql中like或where
11.将连续数据离散化操作或者类似sql中Case When
12.修改列名
13.map、apply、applymap详解
14.povit_table数据透视表的使用
15.数据表的合并和连接
1.drop_duplicates
DataFrame.drop_duplicates(subset=None, keep='first', inplace=False)
subset: 列名,可选,默认为None
keep: {‘first’, ‘last’, False}, 默认值 ‘first’
first: 保留第一次出现的重复行,删除后面的重复行。
last: 删除重复项,除了最后一次出现。
False: 删除所有重复项。
inplace:布尔值,默认为False,是否直接在原数据上删除重复项或删除重复项后返回副本。(inplace=True表示直接在原来的DataFrame上删除重复项,而默认值False表示生成一个副本。)
根据数据的不同情况及处理数据的不同需求,通常会分为两种情况,一种是去除完全重复的行数据,另一种是去除某几列重复的行数据,就这两种情况可用下面的代码进行处理。
#去除完全重复的行数据
DataFrame.drop_duplicates()
#去除某几列重复的行数据
DataFrame.drop_duplicates(subset=['A','B'],keep='first')
#示例,删除positionId重复的行
data_duplicates=data.drop_duplicates(subset=['positionId'],keep='first')
data_duplicates.head()
2.apply函数
在pandas中,有Series和DataFrame两者数据类型。针对这两者类型使用apply函数有略微区别。
2.1 Series.apply
series = pd.Series([20, 21, 12], index=['London','New York','Helsinki'])
series
def square(x):
x=x**2
return x
series.apply(square)
series.apply(lambda x:x**2)
def subtract_custom_value(x, custom_value):
return x-custom_value
series.apply(subtract_custom_value,custom_value=5)
def add_custom_values(x, **kwargs):
for month in kwargs:
x+=kwargs[month]
return x
series.apply(add_custom_values,june=30, july=20, august=25)
series.apply(lambda x:np.log(x+1))
2.2 DataFrame.apply
df = pd.DataFrame([[4, 9,3],[3,5,2],[1,6,7]], columns=['A', 'B','C'])
df
df.apply(lambda x:x['A']+x['C'],axis=1)
df.apply(lambda x:np.sum(x),axis=0)
4.axis理解
axis是apply中的参数,axis=1为横向,axis=0为纵向,而不是行和列。这里axis=1就表示DataFrame根据lambda函数做横向计算。
4.pd.read_csv
使用pd.read_csv()读取数据,对于数据路径有三种办法。一是ipynb文件和使用的数据集在同一个文件中,此时可以直接读取。另一种就是ipynb文件和使用的数据集不在同一个文件中,此时读取数据需要使用相对路径和绝对路径。
#ipynb文件和使用的数据集在同一个文件中
data=pd.read_csv('DataAnalyst.csv',encoding='gbk')
#ipynb文件和使用的数据集不在同一个文件中,使用相对路径
data = pd.read_csv('C:/Users/Administrator/Desktop/秦路数据分析学习/第三周 Excel/DataAnalyst.csv',encoding='gbk')
#ipynb文件和使用的数据集不在同一个文件中,使用绝对路径
data = pd.read_csv('C:\\Users\\Administrator\\Desktop\\秦路数据分析学习\\第三周 Excel\\DataAnalyst.csv',encoding='gbk')
另外,pd.read_csv()的常用参数:
header:指定行数用来作为列名,数据开始行数。如果文件中没有列名,则默认为0,否则设置为None。
sep:默认的为',',即认为文件是以逗号分隔(一般csv文件都是这个格式),若是空格分隔,可以使用"\s+"。
names:用于结果的列名列表,对各列重命名,即添加表头。
如数据有表头,但想用新的表头,可以设置header=0,names=['a','b']实现表头定制。
encoding:一般默认为"utf-8",如果文件中有中文,一般需要使用"gbk"。
5.stack()和unstack()函数
对数据做处理时,经常需要对数据进行reshape。其中,stack和unstack是我们经常用到的操作之一。
stack和unstack是python进行层次化索引的重要操作。层次化索引就是对索引进行层次化分类,便于使用,这里的索引可以是行索引,也可以是列索引。
其实,应用stack和unstack只需要记住下面的知识点即可:
stack: 将数据从”表格结构“变成”花括号结构“,即将其列索引变成行索引。
unstack: 数据从”花括号结构“变成”表格结构“,即要将其中一层的行索引变成列索引。如果是多层索引,则以上函数是针对内层索引(这里是store)。利用level可以选择具体哪层索引。
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
data=DataFrame(np.arange(12).reshape((3,4)),index=pd.Index(['street1','street2','street3']),
columns=pd.Index(['store1','store2','store3','store4']))
print('----------data--------')
print(data)
print('-------------data2----------------------------\n')
data2=data.stack()
data3=data2.unstack()
print(data2)
print('--------------data3---------------------------\n')
print(data3)
data4=data2.unstack(level=0)
print('-------data4----------')
print(data4)
data5=data2.unstack(level=-1) # 默认的level=-1,内层的索引
print('------data5--------')
print(data5)
'''
----------data--------
store1 store2 store3 store4
street1 0 1 2 3
street2 4 5 6 7
street3 8 9 10 11
-------------data2----------------------------
street1 store1 0
store2 1
store3 2
store4 3
street2 store1 4
store2 5
store3 6
store4 7
street3 store1 8
store2 9
store3 10
store4 11
dtype: int64
--------------data3---------------------------
store1 store2 store3 store4
street1 0 1 2 3
street2 4 5 6 7
street3 8 9 10 11
-------data4----------
street1 street2 street3
store1 0 4 8
store2 1 5 9
store3 2 6 10
store4 3 7 11
------data5--------
store1 store2 store3 store4
street1 0 1 2 3
street2 4 5 6 7
street3 8 9 10 11
'''
可以看到:使用stack函数,将data的列索引['store1','store2','store3’,'store4']转变成行索引(第二层),便得到了一个层次化的Series(data2),使用unstack函数,将data2的第二层行索引转变成列索引(默认内层索引,level=-1),便又得到了DataFrame(data3)
下面的例子我们利用level选择具体哪层索引。
data4=data2.unstack(level=0)
print(data4)
'''
street1 street2 street3
store1 0 4 8
store2 1 5 9
store3 2 6 10
store4 3 7 11
'''
我们可以清晰看到,当我们取level=0时,即最外层索引时,unstack把行索引['street1','street2','street3’]变为了列索引。
重塑
6.groupby函数
#按照city和education分组
data_duplicates.groupby(['city','education']).mean()
#按city和education分组并计算bottomSalary最小值,最大值和平均值
data_duplicates.groupby(['city','education'])['bottomSalary'].agg(['min','max','mean'])
data_duplicates.groupby(['city','education']).agg({'bottomSalary':['mean','min'],'topSalary':'max','salary':'count'})
在日常的数据分析中,经常需要将数据根据某个(多个)字段划分为不同的群体(group)进行分析,如电商领域将全国的总销售额根据省份进行划分,分析各省销售额的变化情况,社交领域将用户根据画像(性别、年龄)进行细分,研究用户的使用情况和偏好等。在Pandas中,上述的数据处理操作主要运用groupby完成,在这里着重介绍一下groupby的基本原理及对应的agg、transform和apply操作。
为了后续图解的方便,采用模拟生成的10个样本数据,代码和数据如下:
company=["A","B","C"]
business=['X','Y','Z']
data=pd.DataFrame({
"company":[company[x] for x in np.random.randint(0,len(company),10)],
"business":[business[x] for x in np.random.randint(0,len(business),10)],
"salary":np.random.randint(5,50,10),
"age":np.random.randint(15,50,10)
}
)
data
1.Groupby的基本原理
在pandas中,实现分组操作的代码很简单,仅需一行代码,在这里,将上面的数据集按照company字段进行划分:
company_group=data.groupby(['company'])
company_group
将上述代码输入ipython后,会得到一个DataFrameGroupBy对象
那这个生成的DataFrameGroupBy是啥呢?对data进行了groupby后发生了什么?ipython所返回的结果是其内存地址,并不利于直观地理解,为了看看group内部究竟是什么,这里把group转换成list的形式来看一看:
list(company_group)
[('A', company business salary age
0 A Z 37 21
1 A Y 5 44
3 A X 38 30
4 A Y 31 36
9 A X 28 17),
('B', company business salary age
7 B Y 15 37
8 B Y 15 18),
('C', company business salary age
2 C X 40 17
5 C Y 15 30
6 C Y 19 26)]
转换成列表的形式后,可以看到,列表由三个元组组成,每个元组中,第一个元素是组别(这里是按照company进行分组,所以最后分为了A,B,C),第二个元素的是对应组别下的DataFrame,整个过程可以图解如下:
总结来说,groupby的过程就是将原有的DataFrame按照groupby的字段(这里是company),划分为若干个分组DataFrame,被分为多少个组就有多少个分组DataFrame。所以说,在groupby之后的一系列操作(如agg、apply等),均是基于子DataFrame的操作。理解了这点,也就基本摸清了Pandas中groupby操作的主要原理。下面来讲讲groupby之后的常见操作。
2.agg聚合操作
聚合操作是groupby后非常常见的操作,会写SQL的朋友对此应该是非常熟悉了。聚合操作可以用来求和、均值、最大值、最小值等,下面的表格列出了Pandas中常见的聚合操作。针对样例数据集,如果我想求不同公司员工的平均年龄和平均薪水,可以按照下方的代码进行:
data.groupby(['company']).mean()
如果想对针对不同的列求不同的值,比如要计算不同公司员工的平均年龄以及薪水的中位数,可以利用字典进行聚合操作的指定:
data.groupby(['company']).agg({'salary':'median','age':'mean'})
3.transform
transform是一种什么数据操作?和agg有什么区别呢?为了更好地理解transform和agg的不同,下面从实际的应用场景出发进行对比。
在上面的agg中,我们学会了如何求不同公司员工的平均薪水,如果现在需要在原数据集中新增一列avg_salary,代表员工所在的公司的平均薪水(相同公司的员工具有一样的平均薪水),该怎么实现呢?如果按照正常的步骤来计算,需要先求得不同公司的平均薪水,然后按照员工和公司的对应关系填充到对应的位置,不用transform的话,实现代码如下:
avg_salary=data.groupby(['company']).salary.mean().to_dict()
avg_salary
data['avgsalary'] = data['company'].map(avg_salary)
data
如果使用transform的话,仅需要一行代码:
data['avg_salary']=data.groupby(['company']).salary.transform('mean')
data
还是以图解的方式来看看进行groupby后transform的实现过程(为了更直观展示,图中加入了company列,实际按照上面的代码只有salary列):
图中的大方框是transform和agg所不一样的地方,对agg而言,会计算得到A,B,C公司对应的均值并直接返回,但对transform而言,则会对每一条数据求得相应的结果,同一组内的样本会有相同的值,组内求完均值后会按照原索引的顺序返回结果,如果有不理解的可以拿这张图和agg那张对比一下。
4.apply
apply相比agg和transform而言更加灵活,能够传入任意自定义的函数,实现复杂的数据操作。但apply在groupby后使用apply有什么特别的呢?
对于groupby后的apply,以分组后的子DataFrame作为参数传入指定函数的,基本操作单位是DataFrame,而一般apply的基本操作单位是Series。还是以一个案例来介绍groupby后的apply用法。
假设我现在需要获取各个公司年龄最大的员工的数据,该怎么实现呢?可以用以下代码实现:
def get_oldest_staff(x):
df = x.sort_values(by='age',ascending=False)
return df.iloc[0,:]
data.groupby('company',as_index=False).apply(get_oldest_staff)
这样便得到了每个公司年龄最大的员工的数据,整个流程图解如下:可以看到,此处的apply和上篇文章中所介绍的作用原理基本一致,只是传入函数的参数由Series变为了此处的分组DataFrame。
最后,关于apply的使用,这里有个小建议,虽然说apply拥有更大的灵活性,但apply的运行效率会比agg和transform更慢。所以,groupby之后能用agg和transform解决的问题还是优先使用这两个方法,实在解决不了了才考虑使用apply进行操作。
知乎--Groupby函数
7.数据索引
#单独取出某一列
data_duplicates['city']
#取出多列
data_duplicates[['city','education']]
# 取出某列的某一行
data_duplicates['city'][0]
# 取出某列的某几行
data_duplicates['city'][:10]
#取出某几列的某几行
data_duplicates[['city','education','salary']][:1]
# loc方法索引
'''
DataFrame.loc[行名,列名]
'''
# 取出某几列的某几行
data_duplicates.loc[[0,1,5],['city','education','salary']]
# 取出 city ,education ,salary的0-20行所有索引名称为偶数的数据
data_duplicates.loc[0:21:2,['city','education','salary']]
#iloc方法索引
'''
DataFrame.iloc[行位置,列位置]
'''
#取出某几列的某几行
data_duplicates.iloc[[0,1,5],[0,1,2]]
# 取出前五列的奇数列的0-20行所有索引名称为偶数的数据
data_duplicates.iloc[0:21:2,0:5:2]
#ix方法索引
'''
DataFrame.ix[行位置/行名,列位置/列名]
'''
#筛选出A条件或B条件的样本。这里是组为实验组,页面为新页面或者组为控制组,页面为旧页面的样本
df1=df[((df['group']=='treatment')&(df['landing_page']=='new_page'))|((df['group']=='control')&(df['landing_page']=='old_page'))]
8.数据排序
#Series.sort_values(ascending=False)False降序,True升序
data_duplicates['bottomSalary'].sort_values(ascending=False)
#df.sort_values(by=['A','B'],ascending=False)按by的字段进行排序
data_duplicates.sort_values(by='bottomSalary',ascending=False)
data_duplicates.sort_values(by=['bottomSalary','topSalary'],ascending=False)
9.计算某列有多少个不同的值,类似sql中count(distinct A)
data_duplicates['education'].nunique()
10.数据筛选,类似sql中like或where
#筛选教育背景要求本科及以上
data_duplicates[data_duplicates['education'].isin(['本科','硕士','博士'])]
#筛选受教育背景非大专的样本
data_duplicates[data_duplicates['education']!='大专']
#筛选公司名字中带直播的数据
data_duplicates[data_duplicates['companyShortName'].str.contains('直播')]
#筛选公司名字中带直播或者腾讯的数据
data_duplicates[data_duplicates['companyShortName'].str.contains('直播|腾讯')]
#多个条件筛选--在北京月薪10k起的直播行业招聘
data_duplicates[(data_duplicates['city']=='北京')&(data_duplicates['companyShortName'].str.contains('直播'))&(data_duplicates['bottomSalary']>10)]
11.将连续数据离散化操作或者类似sql中Case When
#根据最低薪资水平创建新的列SalaryType
#方法一
data_duplicates.loc[data_duplicates['bottomSalary']<=10,'SalaryType']='低薪资'
data_duplicates.loc[(data_duplicates['bottomSalary']>10)&(data_duplicates['bottomSalary']<=30),'SalaryType']='中等薪资'
data_duplicates.loc[data_duplicates['bottomSalary']>30,'SalaryType']='高薪资'
#方法二 pd.cut() 左开右闭 (0,10],(10,20],(20,1000]
data_duplicates['SalaryType1'] = pd.cut(data_duplicates['bottomSalary'],[0,10,20,1000],labels=['低薪资','中等薪资','高薪资'])
12.修改列名
data_duplicates.rename(columns={'city':'城市','公司名称':'companyname'},inplace=True)
13.map、apply、applymap详解
pandas数据处理的三板斧在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map、apply和applymap可以解决绝大部分这样的数据处理需求。
boolean=[True,False]
gender=["男","女"]
color=["white","black","yellow"]
data=pd.DataFrame({
"height":np.random.randint(150,190,100),
"weight":np.random.randint(40,90,100),
"smoker":[boolean[x] for x in np.random.randint(0,2,100)],
"gender":[gender[x] for x in np.random.randint(0,2,100)],
"age":np.random.randint(15,90,100),
"color":[color[x] for x in np.random.randint(0,len(color),100) ]
})
data.head()
Series处理
1.map用法
如果需要把数据集中gender列的男替换为1,女替换为0,怎么做呢?绝对不是用for循环实现,使用Series.map()可以很容易做到,最少仅需一行代码。
#第一种方法
data['gender'] = data['gender'].map({'男':1,'女':0})
#第二种方法
#使用函数
def gender_map(x): #这里x表示的是Series的一个元素,对Series元素依次处理
if x=='男':
gender=1
else:
gender=0
return gender
data['gender']=data['gender'].map(gender_map)
那map在实际过程中是怎么运行的呢?请看下面的图解(为了方便展示,仅截取了前10条数据)
不论是利用字典还是函数进行映射,map方法都是把对应的数据逐个当作参数传入到字典或函数中,得到映射后的值。
2.apply用法
同时Series对象还有apply方法,apply方法的作用原理和map方法类似,区别在于apply能够传入功能更为复杂的函数。怎么理解呢?一起看看下面的例子。
假设在数据统计的过程中,年龄age列有较大误差,需要对其进行调整(加上或减去一个值),由于这个加上或减去的值未知,故在定义函数时,需要加多一个参数bias,此时用map方法是操作不了的(传入map的函数只能接收一个参数),apply方法则可以解决这个问题。
def apply_age(x,**kwargs):
for i in kwargs:
x+=kwargs[i]
return x
#以字典的形式传递参数
data['age'] = data['age'].apply(apply_age,list_1=6,list_2=3,list_3=1)
data.head()
总而言之,对于Series而言,map可以解决绝大多数的数据处理需求,但如果需要使用较为复杂的函数,则需要用到apply方法。
DataFrame处理
对于DataFrame而言,基本没有DataFrame.map()的使用,map方法都是针对Series的处理。
1.apply
对DataFrame而言,apply是非常重要的数据处理方法,它可以接收各种各样的函数(Python内置的或自定义的),处理方式很灵活,下面通过几个例子来看看apply的具体使用及其原理。
假设现在需要对data中的数值列分别进行取对数和求和的操作,这时可以用apply进行相应的操作,因为是对列进行操作,所以需要指定axis=0,使用下面的两行代码可以很轻松地解决我们的问题。
#沿着0轴求和
data[['height','weight','age']].apply(lambda x:sum(x),axis=0)
#沿着0轴求log
data[['height','weight','age']]=data[['height','weight','age']].apply(lambda x:np.log(x),axis=0)
data.head()
实现的方式很简单,但调用apply时究竟发生了什么呢?过程是怎么实现的?还是通过图解的方式来一探究竟。(取前五条数据为例)
当沿着轴0(axis=0)进行操作时,会将各列(columns)默认以Series的形式作为参数,传入到你指定的操作函数中,操作后合并并返回相应的结果。
那如果在实际使用中需要按行进行操作(axis=1),那整个过程又是怎么实现的呢?
在数据集中,有身高和体重的数据,所以根据这个,我们可以计算每个人的BMI指数(体检时常用的指标,衡量人体肥胖程度和是否健康的重要标准),计算公式是:体重指数BMI=体重/身高的平方(国际单位kg/㎡),因为需要对每个样本进行操作,这里使用axis=1的apply进行操作,代码如下:
def BMI(x):
weight=x['weight']
height=x['height']/100
BMI = weight/height**2
return BMI
data['BMI'] = data.apply(BMI,axis=1)
data.head()
当apply设置了axis=1对行进行操作时,会默认将每一行数据以Series的形式(Series的索引为列名)传入指定函数,返回相应的结果。
总结一下对DataFrame的apply操作:
1.当axis=0时,对每列columns执行指定函数;当axis=1时,对每行row执行指定函数。
2.无论axis=0还是axis=1,其传入指定函数的默认形式均为Series,可以通过设置raw=True传入numpy数组。
3.对每个Series执行结果后,会将结果整合在一起返回(若想有返回值,定义函数时需要return相应的值)
4.当然,DataFrame的apply和Series的apply一样,也能接收更复杂的函数,如传入参数等,实现原理是一样的,具体用法详见官方文档。
2.applymap
applymap的用法比较简单,会对DataFrame中的每个单元格执行指定函数的操作,虽然用途不如apply广泛,但在某些场合下还是比较有用的,如下面这个例子。
df = pd.DataFrame(
{
"A":np.random.randn(5),
"B":np.random.randn(5),
"C":np.random.randn(5),
"D":np.random.randn(5),
"E":np.random.randn(5),
}
)
df
现在想将DataFrame中所有的值保留两位小数显示,使用applymap可以很快达到你想要的目的,代码和图解如下:
df.applymap(lambda x:'%.2f'%x)
14.pivot_table数据透视表
从功能上讲,Pandas 中用透视表 (pivot table) 和 Excel 里面的透视表是一样的。
pivot_table参数的含义
Pivot 字面意思是支点,即上图中的 index 和 columns 指定的行和列标签,支点可想理解成数据 (values) 在哪个维度上做整合 (aggfunc),再吧 NaN 值用 fill_value 替代,按行按列加总 (margin=True)。
boolean=[True,False]
gender=["男","女"]
color=["white","black","yellow"]
data=pd.DataFrame({
"height":np.random.randint(150,190,100),
"weight":np.random.randint(40,90,100),
"smoker":[boolean[x] for x in np.random.randint(0,2,100)],
"gender":[gender[x] for x in np.random.randint(0,2,100)],
"age":np.random.randint(15,90,100),
"color":[color[x] for x in np.random.randint(0,len(color),100) ]
})
data.head()
设置"单行"为pivot
创建透视表的 pivot_table() 函数里面的参数设置很多,学习它最有效的方式是每一步设置一个参数,检查结果是否符合预期。
先从最简单的语法开始,只设置 index='gender',通用语法如下:
data.pivot_table(index='gender')
从上表可以看到,年龄、身高、体重、甚至bool类型的是否吸烟都按某种聚合方式进行了合并了。现在大概可以猜出 pivot_table() 函数中有个参数用来设置整合方式,而默认值为平均。
设置"多行"为pivot
上例设置单个 index,接下来看看设置多个 index 的结果是什么样的。这时用列表来存储多个 index。通用语法如下:
data.pivot_table(index=['gender','smoker'])
到目前为止,我们只设置了 index,那为什么只在 age、height和weight三列上做整合呢?因为这两列的值是数值型 (int, float),而其他列的值是非数值型 (object)。
设定被整合的数据
如果只看 age列下的整合结果,只需设置 values='age' 或者 values=['age'],通用语法如下:
pd.pivot_table(df, index=label_list, values=label_list)
data.pivot_table(index=['gender','smoker'],values='age')
设定整合函数
默认整合函数是求平均,如果要用求和的函数需要设置 aggfunc=np.sum,通用语法为
pd.pivot_table(df, index=label_list, values=label_list, aggfunc=func)
data.pivot_table(index=['gender','smoker'],values='age',aggfunc='sum')
aggfunc 参数可以被设置为多个函数,用列表储存,通用语法为
pd.pivot_table(df, index=label_list, values=label_list, aggfunc=func_list)
data.pivot_table(index=['gender','smoker'],values='age',aggfunc=['sum','mean'])
设定列为pivot
如果进一步想看按吸烟划分后的整合结果,可以设置 columns=[''smoker"]
data.pivot_table(index=['gender'],columns=['smoker'],values='age',aggfunc=['mean'])
若表结果中有 NaN ,可设置 fill_value=0 用零替代。
要看总计怎么办?设置 margins=True 就可以了。
aggfunc 参数还可以传进一个字典来实现不同列下应用不同的整合函数,语法如下:
pd.pivot_table( df, index=["Counterparty","Trader","Category"],
values=["Value","Quantity"],
aggfunc={"Value":np.sum, "Quantity":len},
fill_value=0,
margins=True )
再进一步,不同列还可以应用多个函数,只需把函数名称变成函数列表就可以了。语法如下:
pd.pivot_table( df, index=["Counterparty","Trader","Category"],
values=["Value","Quantity"],
aggfunc={"Value":[np.sum, min, max],
"Quantity":len},
fill_value=0 )
15.数据表的合并与连接
数据表可以按「键」合并,用 merge 函数;可以按「轴」来连接,用 concat 函数。
15.1合并
按键 (key) 合并可以分「单键合并」和「多键合并」。
单键合并
单键合并用merge函数,语法如下:
pd.merge(df1,df2,how=s,on=c)
c是df1和df2共有的一栏,合并方式(how=s)有四种:
1.左连接(left join):合并之后显示df1的所有行
2.右连接(right join):合并之后显示df2的所有行
3.外连接(outer join)合并df1和df2的所有行
4.内连接(inner join):合并所有行(默认情况)
首先创建两个 DataFrame:
df_price:4 天的价格 (2019-01-01 到 2019-01-04)
df_volume:5 天的交易量 (2019-01-02 到 2019-01-06)
df_price = pd.DataFrame( {'Date': pd.date_range('2019-1-1', periods=4),
'Adj Close': [24.42, 25.00, 25.25, 25.64]})
df_volume = pd.DataFrame( {'Date': pd.date_range('2019-1-2', periods=5),
'Volume' : [56081400, 99455500, 83028700, 100234000, 73829000]})
接下来用 df_price 和 df_volume 展示四种合并。left join:
pd.merge(df_price,df_volume,how='left')
right join:
pd.merge(df_price,df_volume,how='right')
outer join:
pd.merge(df_price,df_volume,how='outer')
inner join:
pd.merge(df_price,df_volume,how='inner')
多键合并
多键合并用的语法和单键合并一样,只不过 on=c 中的 c 是多栏。
pd.merge( df1, df2, how=s, on=c )
首先创建两个 DataFrame:
portfolio1:3 比产品 FX Option, FX Swap 和 IR Option 的数量
portfolio2:4 比产品 FX Option (重复名称), FX Swap 和 IR Swap 的数量
porfolio1 = pd.DataFrame({'Asset': ['FX', 'FX', 'IR'],
'Instrument': ['Option', 'Swap', 'Option'],
'Number': [1, 2, 3]})
porfolio2 = pd.DataFrame({'Asset': ['FX', 'FX', 'FX', 'IR'],
'Instrument': ['Option', 'Option', 'Swap', 'Swap'],
'Number': [4, 5, 6, 7]})
pd.merge(porfolio1,porfolio2,on=['Asset','Instrument'],how='left')
15.2连接
Numpy 数组可相互连接,用 np.concat;同理,Series 也可相互连接,DataFrame 也可相互连接,用 pd.concat。
连接Series
在 concat 函数也可设定参数 axis:
axis = 0 (默认),沿着轴 0 (行) 连接,得到一个更长的 Series
axis = 1,沿着轴 1 (列) 连接,得到一个 DataFrame
被连接的 Series 它们的 index 可以重复 (overlapping),也可以不同。
s1 = pd.Series([0, 1], index=['a', 'b'])
s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = pd.Series([5, 6], index=['f', 'g'])
#沿着「轴 1」连接得到一个 DataFrame。
pd.concat([s1,s2,s3],axis=1)
将 s1 和 s3 沿「轴 0」连接来创建 s4,这样 s4 和 s1 的 index 是有重复的。
s4 = pd.concat([s1,s3],axis=0)
pd.concat([s1,s4],axis=1)
#将 s1 和 s4 沿「轴 1」内连接 (即只连接它们共有 index 对应的值)
pd.concat([s1,s4],axis=1,join='inner')
连接DataFrame
连接 DataFrame 的逻辑和连接 Series 的一模一样。
沿着行连接(axis=0):
先创建两个 DataFrame,df1 和 df2。
df1 = pd.DataFrame( np.arange(12).reshape(3,4),
columns=['a','b','c','d'])
df2 = pd.DataFrame( np.arange(6).reshape(2,3),
columns=['b','d','a'])
沿着行连接分两步
1.先把 df1 和 df2 列标签补齐
2.再把 df1 和 df2 纵向连起来
pd.concat([df1,df2],axis=0,ignore_index=True)
沿着列连接(axis=1):
先创建两个 DataFrame,df1 和 df2。
df1 = pd.DataFrame( np.arange(6).reshape(3,2),
index=['a','b','c'],
columns=['one','two'] )
df2 = pd.DataFrame( 5 + np.arange(4).reshape(2,2),
index=['a','c'],
columns=['three','four'])
pd.concat([df1,df2],axis=1)
网友评论