美文网首页python
学习所见的pandas操作总结

学习所见的pandas操作总结

作者: 走二仙桥丶 | 来源:发表于2020-06-12 21:57 被阅读0次

    希望自己在兵荒马乱中保持韧性,发现宝藏。


    目录

    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的具体使用及其原理。

    在进行具体介绍之前,首先需要介绍一下DataFrame中axis的概念,在DataFrame对象的大多数方法中,都会有axis这个参数,它控制了你指定的操作是沿着0轴还是1轴进行。axis=0代表操作对列columns进行,axis=1代表操作对行row进行,如下图所示。 如果还不是很了解,没关系,下面会分别对apply沿着0轴以及1轴的操作进行讲解,继续往下走。

    假设现在需要对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)
    

    相关文章

      网友评论

        本文标题:学习所见的pandas操作总结

        本文链接:https://www.haomeiwen.com/subject/uzaetktx.html