交易流水指标统计——pandas

1、根据交易流水,计算每个交易交易对象的如下指标,
总收入笔数、总收入月数、最大月收入笔数、最大月收入笔数所在日期(年月日格式)

import pandas as pd
path = r"C:\Users\xxx\Desktop\科技数据.xlsx"
df = pd.read_excel(path)                  #读取excel数据
df['_COL0']= pd.to_datetime(df['_COL0'])  #日期数据格式转换
res = df[df['_COL4 '] == '收入']          #查询收入数据
res.reset_index(inplace=True, drop=True)
res.info() 
res.head() #查看数据
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2134 entries, 0 to 2133
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   id      2134 non-null   object        
 1   _COL0   2134 non-null   datetime64[ns]
 2   x       2134 non-null   object        
 3   _COL4   2134 non-null   object        
 4   _col5   2134 non-null   float64       
 5   交易对方    2133 non-null   object        
dtypes: datetime64[ns](1), float64(1), object(4)
memory usage: 100.2+ KB
id _COL0 x _COL4 _col5 交易对方
0 1000050001202305060010\n153222358 2023-05-06 18:10:45 转账 收入 676.0 三巷7号303
1 1000050001202305060717\n985751052 2023-05-06 18:10:10 转账 收入 1120.0 北围401
2 1000050001202305061319\n409873668 2023-05-06 17:32:31 转账 收入 1100.0 百花洞北围\n501
3 1000050001202305061412\n834865884 2023-05-06 17:31:41 转账 收入 2002.0 一巷5号店\n铺童权枝15\n323538188
4 1000050001202305060217\n908459280 2023-05-06 17:26:32 转账 收入 887.0 一巷5号401\n(交租人)
 # 计算每个交易对象的指标
def max_count_date(x):
    idx = x.groupby(x['_COL0'].dt.month)['_col5'].transform('count').idxmax()
    return  res.iloc[idx,1].strftime('%Y%m%d')

grouped = res.groupby('交易对方')
summary = grouped.agg(总收入笔数=('交易对方', 'count'), 总收入月数=('_COL0',lambda x: x.dt.month.nunique()) )
max_monthly_income = grouped.apply(lambda x: x['_col5'].groupby(x['_COL0'].dt.month).count().max())
summary['最大月收入笔数'] = max_monthly_income.astype('int')
summary['最大月收入笔数所在日期'] = grouped.apply(max_count_date)
summary                  #查看指标结果
总收入笔数 总收入月数 最大月收入笔数 最大月收入笔数所在日期
交易对方
.San 1 1 1 20230126
/ 20 6 5 20230214
166858006\n45 1 1 1 20220619
30号201(\n已搬) 1 1 1 20220802
30号202 3 3 1 20230506
... ... ... ... ...
龙江802烧\n烤 6 5 2 20230119
龙江804(电\n费改1元) 1 1 1 20220702
龙江901业\n主 10 10 1 20230405
ꦿ封訫ꦿ鎖\n愛꧔ꦿএ᭄ 1 1 1 20230412
꧁꫞꯭独一无\n二꫞꧂ 2 2 1 20221103

502 rows × 4 columns


2、将上面计算的指标匹配到原始数据表中,按交易对象(人名)匹配,原始表新增上面几个指标列。

# 将指标匹配到原始数据表中
df = df.merge(summary, on='交易对方', how='left')
df[df.duplicated('交易对方')].sort_values('交易对方') #查看指标是否正确
id _COL0 x _COL4 _col5 交易对方 总收入笔数 总收入月数 最大月收入笔数 最大月收入笔数所在日期
164 1800008005230419011159\n1100710500 2023-04-19 15:55:11 零钱通转出-\n到零钱 其他 6000.0 / 20.0 6.0 5.0 20230214
1806 4200001705202212059573\n010442 2022-12-05 16:34:49 转入零钱通-\n来自零钱 其他 7714.0 / 20.0 6.0 5.0 20230214
1777 4200001709202212080999\n467748 2022-12-08 12:05:07 转入零钱通-\n来自零钱 其他 9806.0 / 20.0 6.0 5.0 20230214
1516 4200001715202301033827\n069012 2023-01-03 22:01:40 转入零钱通-\n来自零钱 其他 193.5 / 20.0 6.0 5.0 20230214
800 4200001788202303023467\n241839 2023-03-02 18:29:55 转入零钱通-\n来自零钱 其他 10321.5 / 20.0 6.0 5.0 20230214
... ... ... ... ... ... ... ... ... ... ...
638 1000050001202303070411\n163291909 2023-03-07 15:31:25 转账 收入 332.0 龙江901业\n主 10.0 10.0 1.0 20230405
2329 1000050001202210051317\n077385423 2022-10-05 17:41:53 转账 收入 591.0 龙江901业\n主 10.0 10.0 1.0 20230405
1752 1000050001202212081215\n944574957 2022-12-08 15:34:45 转账 收入 338.0 龙江901业\n主 10.0 10.0 1.0 20230405
2145 1000050001202211050215\n131777661 2022-11-05 14:03:06 转账 收入 388.0 龙江901业\n主 10.0 10.0 1.0 20230405
2224 1000039901000210306181\n885746052 2022-10-30 15:31:23 微信红包 收入 88.0 ꧁꫞꯭独一无\n二꫞꧂ 2.0 2.0 1.0 20221103

2597 rows × 10 columns


3、将交易月份数大于等于2的交易对象的前两个月定义为1,2,交易月份数小于2的不定义。并匹配到原始表中,即,原始表新增一列,first_twoM。

df['first_twoM'] = np.nan
def get_first_two_m(x):
    months = x.dt.month.drop_duplicates()
    if len(months) >=2:
        first_t = months[0:2].values
        arr1 = x.dt.month.values == first_t[0]
        idx1 = np.where(arr1 == True)
        arr2 = x.dt.month.values == first_t[1]
        arr2 = np.where(arr2, 2, np.nan)
        arr2[idx1]  = 1
        return arr2
    
df.sort_values(['交易对方', '_COL0'], inplace=True)
df['first_twoM'] = df.groupby('交易对方')['_COL0'].transform(get_first_two_m)
df        
id _COL0 x _COL4 _col5 交易对方 总收入笔数 总收入月数 最大月收入笔数 最大月收入笔数所在日期 first_twoM 交易月份是否连续
1293 1000039801000301266118\n805364803 2023-01-26 19:03:36 微信红包 收入 30.0 .San 1.0 1.0 1.0 20230126 NaN NaN
2584 1000039801202209056110\n700265037 2022-09-06 14:35:30 微信红包-退\n款 收入 1.0 / 20.0 6.0 5.0 20230214 1.0 0.0
2154 1000050001202211040915\n379319646 2022-11-04 21:08:44 转账-退款 收入 2250.0 / 20.0 6.0 5.0 20230214 2.0 1.0
2036 4200001605202211089277\n950418 2022-11-08 00:48:37 转入零钱通-\n来自零钱 其他 1.0 / 20.0 6.0 5.0 20230214 2.0 1.0
2034 4200001627202211082029\n141916 2022-11-08 00:50:31 转入零钱通-\n来自零钱 其他 12500.0 / 20.0 6.0 5.0 20230214 2.0 1.0
... ... ... ... ... ... ... ... ... ... ... ... ...
199 1000039801000304126238\n646974024 2023-04-12 22:45:58 微信红包 收入 100.0 ꦿ封訫ꦿ鎖\n愛꧔ꦿএ᭄ 1.0 1.0 1.0 20230412 NaN NaN
2224 1000039901000210306181\n885746052 2022-10-30 15:31:23 微信红包 收入 88.0 ꧁꫞꯭独一无\n二꫞꧂ 2.0 2.0 1.0 20221103 1.0 1.0
2196 1000039801000211036179\n418892051 2022-11-03 13:01:38 微信红包 收入 2.0 ꧁꫞꯭独一无\n二꫞꧂ 2.0 2.0 1.0 20221103 2.0 1.0
2045 1000050001221107000531\n19264996526500 2022-11-07 16:57:13 转账 支出 220.0 (违约退租\n)30号302 NaN NaN NaN NaN NaN NaN
1674 1000107101202212160157\n5756505506 2022-12-16 19:11:46 二维码收款 收入 254.0 NaN NaN NaN NaN NaN NaN NaN

3283 rows × 12 columns


4、根据交易日期,将连续的月份定义为1,不连续定义为0。例如一个人交易月份
202201、202202、202205、202206 、202208、202210、202211、202302

def transaction_date(x):
    x.sort_values(inplace=True)
    month = x.dt.month.drop_duplicates()
    if len(month) <=1 :
        return           #0 只有一个月份数的可以在这里设置返回零
    dif1 = abs(month.diff(periods=-1))
    dif1 = dict(zip(month.values,dif1.values))
    dif2 = abs(month.diff(periods=1))
    dif2 =dict(zip(month.values,dif2.values))
    transaction_month = set([i for i,j in dif2.items() if j in [1,11]] + [i for i,j in dif1.items() if j in [1,11]])
    return x.dt.month.isin(transaction_month).astype('int')

df['交易月份是否连续'] = df.groupby('交易对方')['_COL0'].transform(transaction_date)
df
id _COL0 x _COL4 _col5 交易对方 总收入笔数 总收入月数 最大月收入笔数 最大月收入笔数所在日期 first_twoM 交易月份是否连续
1293 1000039801000301266118\n805364803 2023-01-26 19:03:36 微信红包 收入 30.0 .San 1.0 1.0 1.0 20230126 NaN NaN
2584 1000039801202209056110\n700265037 2022-09-06 14:35:30 微信红包-退\n款 收入 1.0 / 20.0 6.0 5.0 20230214 1.0 0.0
2154 1000050001202211040915\n379319646 2022-11-04 21:08:44 转账-退款 收入 2250.0 / 20.0 6.0 5.0 20230214 2.0 1.0
2036 4200001605202211089277\n950418 2022-11-08 00:48:37 转入零钱通-\n来自零钱 其他 1.0 / 20.0 6.0 5.0 20230214 2.0 1.0
2034 4200001627202211082029\n141916 2022-11-08 00:50:31 转入零钱通-\n来自零钱 其他 12500.0 / 20.0 6.0 5.0 20230214 2.0 1.0
... ... ... ... ... ... ... ... ... ... ... ... ...
199 1000039801000304126238\n646974024 2023-04-12 22:45:58 微信红包 收入 100.0 ꦿ封訫ꦿ鎖\n愛꧔ꦿএ᭄ 1.0 1.0 1.0 20230412 NaN NaN
2224 1000039901000210306181\n885746052 2022-10-30 15:31:23 微信红包 收入 88.0 ꧁꫞꯭独一无\n二꫞꧂ 2.0 2.0 1.0 20221103 1.0 1.0
2196 1000039801000211036179\n418892051 2022-11-03 13:01:38 微信红包 收入 2.0 ꧁꫞꯭独一无\n二꫞꧂ 2.0 2.0 1.0 20221103 2.0 1.0
2045 1000050001221107000531\n19264996526500 2022-11-07 16:57:13 转账 支出 220.0 (违约退租\n)30号302 NaN NaN NaN NaN NaN NaN
1674 1000107101202212160157\n5756505506 2022-12-16 19:11:46 二维码收款 收入 254.0 NaN NaN NaN NaN NaN NaN NaN

3283 rows × 12 columns


  • 自定义excel表格式导出
class writer():
    def __init__(self, df: list, sheet_name: list, key: list, path: str):
        self.df = df                 #dataframe数据
        self.sheet_name = sheet_name #sheet名称
        self.key = key               #需要上色字段
        self.path = path             #excel保存地址
    def save(self):
        path = "C:/Users/15028/Desktop/{}{}(导出时间{}).xlsx".format(pd.Timestamp.now().strftime("%y%m%d"),self.path,pd.Timestamp.now().strftime("%H时%M分%S秒"))
        writer = pd.ExcelWriter(path,engine='xlsxwriter') #创建pandas.ExcelWriter实例,赋值给writer
        for j in range(len(self.sheet_name)):            #遍历sheet名称列表
            #创建sheet表并写入dataframe数据
            self.df[j].to_excel(writer, sheet_name=self.sheet_name[j], index=False #不写入索引index=False
                                ,freeze_panes=(1,2))      #设置固定1、2列(固定列无法左右移动)
            workbook = writer.book                        #工作蒲格式方法
            worksheet = writer.sheets[self.sheet_name[j]] #读取sheet表
            #  计算每列的合适字符宽度,放到元组中
            widths = (self.df[j].astype(str).applymap(lambda x: 40 if len(x)>61 else len(x)+9 if len(x)<9 else len(x)).agg(max).values)
            #设置每列宽度大小
            [worksheet.set_column(i, i, width) for i, width in enumerate(widths)]  #计算的宽度,设置列宽
            color = ['#03A89E','#00C78C','#FFFFCD','#FFC0CB','#808A87','#FFE384','#ED9121','#40E0D0','#FFFFCD']*5 #颜色列表
            (worksheet.set_column(i,i,widths[i],workbook.add_format({
    
    'fg_color': color[i-11],
                                                        'valign': 'vcenter',# 垂直对齐方式
                                                        'font_size': 10,    #字体大小
                                                        'border': 4,        #单元格边框宽度
                                                        'align': 'left'    # 水平对齐方式
                                                                    })) for 
            i,x in enumerate(self.df[j].columns) if self.df[j].columns[i] in self.key[0])
            #设置首行宽度 
            worksheet.set_row(0,20,workbook.add_format({
    
    'fg_color':'#40E0D0'#背景颜色
                                                        ,'bold': True,#字体加粗
                                                        'valign': 'vcenter',# 垂直对齐方式
                                                        'font_size': 16, #字体大小
                                                        'border': 10, #单元格边框宽度
                                                        'align': 'left' # 水平对齐方式
                                                       }))
#         worksheet.set_column("A:B",None,None,{'hidden':1})  #A至B列,隐藏
        writer.close()
writer1 = writer(df=[df],path='交易数据',key=[df.columns[-6:]],sheet_name=['交易表'])
writer1.save()

猜你喜欢

转载自blog.csdn.net/qq_20163065/article/details/131884053