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

2019-08-19  本文已影响0人  Stone0823

工作中经常需要对数据进行行转列加工处理,输出数据作为报表,类似于 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()
上一篇下一篇

猜你喜欢

热点阅读