工作中经常需要对数据进行行转列加工处理,输出数据作为报表,类似于 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.Series
,Series
是的类型正好是 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()
网友评论