美文网首页
pandas 行转列一种典型输出报表的解决方法

pandas 行转列一种典型输出报表的解决方法

作者: Stone0823 | 来源:发表于2019-08-19 14:42 被阅读0次

    工作中经常需要对数据进行行转列加工处理,输出数据作为报表,类似于 SQL 语句中 case when 的处理。下图的数据来自工作中实际处理数据的简化,源数据格式如下:



    表格是一个财务有关项目的数据,ENTITY 表示公司实体,ACCOUNT 是会计科目,S/H 表示借贷方,PROJET_TYPE 是项目类型,PROJECT_CODE 是项目编码。源数据我已经放在 github 上。

    需要根据某一会计期间,比如 2018 年 4 月,反映月份的投资成本 (140401科目)和公允价值 (140404科目)的变化情况:

    首先使用 read_csv() 方法读取数据到 DataFrame 中:

    import pandas as pd
    import numpy as np
    
    df = pd.read_csv('https://raw.githubusercontent.com/stonewm/python-practice-projects/master/pandas%20sample%20data/project-listing.csv')
    

    假如现在编制 2018 年 4 月报表,首先获取 2018 年的年初余额。科目 140401 是原始投资科目,140404 是投资价值变化科目。获取的条件是:科目为 140401 且 年份小于 2018。

    需要介绍一下 numpy.where() 函数。这个函数的语法为:

    out = numpy.where(condition[, x, y])
    

    x, y 为 array-like 的数据结构,当 condtion 为 True 时,返回 x,否则返回 y。比如下面的例子:

    >>> a = np.random.randint(1,10,8).reshape(2,4)
    >>> b = np.random.randint(1,10,8).reshape(2,4)
    >>> a
    array([[6, 8, 8, 8],
           [1, 3, 9, 2]])
    >>> b
    array([[9, 7, 6, 8],
           [7, 8, 2, 7]])
    >>> np.where(True, a+2, b+2)
    array([[ 8, 10, 10, 10],
           [ 3, 5, 11, 4]])
    

    a 和 b 都是一个 2 * 4 的数组,当条件为 True 时,返回值为一个数组,数组的值是 a 的 每一个元素 + 2。

    现在用 df 的数据来进行演练。我们知道 DataFrame 的每一列数据类型是 pandas.core.series.SeriesSeries 是的类型正好是 ndarray (One-dimensional ndarray with axis labels (including time series),所以可以使用 numpy.where() 方法进行处理:

    account = df['ACCOUNT']
    txyear = df['YEAR']
    amount = df['AMOUNT']
    begin_cost = np.where((account==140401) & (txyear<2018), amount, 0)
    

    显示一下 begin_cost:

    array([0.00000000e+00, 3.24717000e+08, 7.60000000e+06, 2.44102600e+05,
           1.00000000e+06, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
           0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
           0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.93538440e+06,
           8.84261079e+07, 3.90906100e+05, 7.90258530e+06, 0.00000000e+00,
           0.00000000e+00])
    

    注意在 numpy.where() 函数中,多个条件时,要将每个条件用括号括起来。我们用这个范围为 df 增加一列:

    df['BEGIN_COST'] = np.where(
        (df['ACCOUNT']==140401) & (df['YEAR']<2018), df['AMOUNT'], 0
    )
    

    在 jupyter notebook 中显示增加 BEGIN_COST 列之后的 Data Frame:


    其他列的方法相同,这里贴出代码:

    df['BEGIN_COST'] = np.where(
        (df['ACCOUNT']==140401) & (df['YEAR']<2018), df['AMOUNT'], 0
    )
    
    df['BEGIN_VAR'] = np.where(
        (df['ACCOUNT']==140404) & (df['YEAR'] <2018), df['AMOUNT'], 0)
    
    df['PER_COST_ADD'] = np.where(
        (df['ACCOUNT']==140401) & (df['YEAR']==2018) & (df['MONTH']<=4) & (df['DIRECTION']=='S'),
        df['AMOUNT'], 0
    )
    
    df['PER_VAR_ADD'] = np.where(
        (df['ACCOUNT']==140404) & (df['YEAR']==2018) & (df['MONTH']<=4) & (df['DIRECTION']=='S'),
        df['AMOUNT'], 0
    )
    
    df['PER_COST_DECT'] = np.where(
        (df['ACCOUNT']==140401) & (df['YEAR']==2018) & (df['MONTH']<=4) & (df['DIRECTION']=='H'),
        df['AMOUNT'], 0
    )
    
    df['PER_VAR_DECT'] = np.where(
        (df['ACCOUNT']==140404) & (df['YEAR']==2018) & (df['MONTH']<=4) & (df['DIRECTION']=='H'),
        df['AMOUNT'], 0
    )
    
    prj_summarized = df[['PROJ_CODE', 'BEGIN_COST', 'BEGIN_VAR', 'PER_COST_ADD', 'PER_VAR_ADD', 'PER_COST_DECT', 'PER_VAR_DECT']].groupby('PROJ_CODE').sum()
    

    相关文章

      网友评论

          本文标题:pandas 行转列一种典型输出报表的解决方法

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