前言
在业务数据分析中,特别是和时间相关的数据,会经常要判断数据的变化情况,比如是否是增长还是降低,或是持平。
需求
以数据中最后的月份为基础,来看它最近的数据变化,并将变化情况标记在本行的最后一列中。
思路
整体思路是写一个函数,传入每一行(axis 为 1)数据,返回要标记的文本内容。
这个函数在处理时,可以按以下顺序进行:
- 对 Series 求位差,得到与邻近月份相差数
- 对位差上的数用 NumPy 的 np.sign() 方法求得其符号,大于 0 时为 1,小于 0 时为 -1,为 0 时 返回
0,分别代码数据的变化趋势 - 6 月的符号值是当前变化趋势
- 判断所有的符号值与 6 月是否相同,得到一个布尔序列,对应位置上 True 的说明变化趋势相同
- 然后利用累乘的计算特点,True 按 1 计算,如果遇到 Flase(按 0)后边的全为 0,将布尔序列变为 0-1 序列
- 最后计算有多少个 1,可直接对序列求和得到,就是连续的月数
二、使用步骤
1.引入库
代码如下(示例):
import pandas as pd
import numpy as np
2.读入数据
代码如下(示例):
np.random.seed(4096)
df = pd.DataFrame(np.random.randint(0, 100, (8, 6)),
columns=pd.array([*'123456'])+'月'
)
df.iloc[4, 1:] = df.iloc[4,1]
df
def func(ser: pd.Series):
ser = ser.diff().apply(np.sign)
type_str = {1: '增长', -1: '降低', 0: '持平'}.get(ser.iloc[-1])
ser = (ser == ser.iloc[-1]).iloc[::-1]
num = ser.cumprod().sum()
return f'连续{num}个月{type_str}'
df.assign(连续增减=df.apply(func, axis=1))
# 另外我们还可以编写迭代方法来处理数据,同样可以得到结果。如:
def func(ser: pd.Series):
ser = iter(ser.iloc[::-1])
cur, nxt = next(ser), next(ser)
type_str = {1: '增长', -1: '降低', 0: '持平'}.get(cur)
n = 1
while cur == nxt:
n += 1
cur = nxt
nxt = next(ser)
return f'连续{n}个月{type_str}'
(
df.diff(axis=1)
.applymap(np.sign)
.apply(func, axis=1)
)
# 还可以通过第一种方法用累加的思路完成:
(
df.diff(axis=1)
.applymap(np.sign)
.set_index('6月', drop=False)
.apply(lambda x: x!=x.iloc[-1], axis=1)
.apply(lambda x: x.iloc[::-1].cumsum(), axis=1)
.apply(lambda x: sum(x==0), axis=1)
.rename({1: '增长', -1: '降低', 0: '持平'})
)
df.assign(连续增减='连续'+_.astype(str).values+'个月'+_.index)
总结
以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。