第一部分 数据统计
import numpy as np
import pandas as pd
1、创建DataFrame对象
生成50行5列【20,1000)之间的随机整数
data=np.random.randint(20,1000,[20,5])
index=range(1,21)
columns=['中国','美国','英国','德国','法国']
df=pd.DataFrame(data=data,index=index,columns=columns)
print(df)
中国 美国 英国 德国 法国
1 687 230 260 839 27
2 694 750 731 214 984
3 146 78 653 990 462
4 214 951 552 164 857
5 253 473 827 102 649
6 445 678 941 268 55
7 510 740 532 603 213
8 924 877 462 713 165
9 383 75 369 376 136
10 720 982 117 374 225
11 30 900 541 540 755
12 855 891 343 998 905
13 52 886 828 360 282
14 787 936 452 455 369
15 704 958 827 796 555
16 140 445 491 674 978
17 993 383 878 508 290
18 568 697 550 51 819
19 96 938 735 794 158
20 345 172 606 630 511
2、计算总数
增加一列数据
df['总数']=df.sum(axis=1)
print(df.head())
中国 美国 英国 德国 法国 总数
1 668 537 491 314 338 2348
2 775 737 874 801 249 3436
3 675 558 948 821 459 3461
4 466 150 572 590 482 2260
5 388 325 992 572 52 2329
3、计算各国均值
增加一行数据
df.loc['均值']=df.mean(axis=0)
print(df.tail(5))
中国 美国 英国 德国 法国 总数
17 333.0 54.00 496.00 595.00 752.00 2230.0
18 267.0 141.00 405.00 393.00 669.00 1875.0
19 551.0 946.00 729.00 416.00 701.00 3343.0
20 987.0 824.00 889.00 376.00 187.00 3263.0
均值 620.6 459.15 515.75 452.85 495.85 2544.2
4、求每个国家的最大值
print(df.max())
中国 993.0
美国 942.0
英国 936.0
德国 998.0
法国 934.0
总数 3958.0
5、求每个国家的最小值
print(df.min())
中国 31.0
美国 133.0
英国 38.0
德国 27.0
法国 24.0
总数 1559.0
6、求每个国家的中位数
print(df.median())
中国 649.00
美国 527.95
英国 426.00
德国 583.00
法国 479.00
总数 2660.45
7、求每个国家的众数
获取各列众数
print(df.mode())
中国 美国 英国 德国 法国 总数
0 23.00 56.0 120.0 118.00 57.00 1197.00
1 35.00 57.0 132.0 154.00 88.00 1557.00
2 74.00 124.0 246.0 177.00 219.00 1749.00
3 100.00 133.0 322.0 214.00 256.00 2078.00
4 208.00 296.0 383.0 274.00 270.00 2311.00
5 259.00 318.0 394.0 284.00 274.00 2332.00
6 264.00 377.0 433.0 370.00 429.00 2466.00
7 337.00 472.0 479.0 448.00 446.00 2526.00
8 415.00 551.4 502.0 460.00 479.00 2644.05
9 469.35 586.0 541.0 512.95 499.00 2695.00
10 482.00 689.0 562.5 522.00 521.00 2826.00
11 532.00 697.0 565.0 538.00 547.85 2886.00
12 538.00 730.0 587.0 589.00 627.00 2892.00
13 558.00 734.0 664.0 596.00 696.00 2953.00
14 572.00 775.0 691.0 613.00 707.00 2972.00
15 622.00 783.0 769.0 670.00 833.00 2981.00
16 757.00 799.0 798.0 731.00 867.00 3174.00
17 804.00 814.0 869.0 747.00 882.00 3185.00
18 883.00 849.0 892.0 860.00 889.00 3283.00
19 938.00 854.0 902.0 935.00 948.00 3292.00
20 986.00 885.0 961.0 959.00 970.00 3526.00
获取某一列众数
print(df['总数'].mode())
0 1010.0
1 1273.0
2 1564.0
3 1698.0
4 1763.0
5 2062.0
6 2080.0
7 2325.0
8 2326.0
9 2341.0
10 2345.0
11 2360.4
12 2441.0
13 2461.0
14 2480.0
15 2750.0
16 3022.0
17 3073.0
18 3241.0
19 3290.0
20 3663.0
Name: 总数, dtype: float64
存在多个众数的时,获取众数的均值
print(df['总数'].mode().mean())
2698.15
8、求中国的众数
如果存在多个众数,则求他们的均值
print(df['中国'].mode())
0 378.0
Name: 中国, dtype: float64
9、方差和标准差
生成2行10列【50,120)之间的随机整数
np.random.seed(521) #设定随机种子,使随机数固定下来
data1=np.random.randint(50,120,[2,10])
data2=np.random.randint(50,150,[2,10])
data=np.vstack((data1,data2)) #拼接data1,data2
index=['Jack','Naccy','Tomi','Kattle']
columns=[f'第{i}次测试成绩' for i in range(1,11)]
print(data)df=pd.DataFrame(data=data,index=index,columns=columns)
print(df)
[[ 68 97 92 66 75 61 96 100 118 77]
[ 99 74 95 118 109 100 74 74 103 84]
[143 131 74 128 65 99 108 128 81 51]
[ 62 121 115 137 129 109 143 88 114 115]]
第1次测试成绩 第2次测试成绩 第3次测试成绩 第4次测试成绩 ... 第7次测试成绩 第8次测试成绩 第9次测试成绩 第10次测试成绩
Jack 68 97 92 66 ... 96 100 118 77
Naccy 99 74 95 118 ... 74 74 103 84
Tomi 143 131 74 128 ... 108 128 81 51
Kattle 62 121 115 137 ... 143 88 114 115
[4 rows x 10 columns]
10、求方差、标准差和变异系数
df['方差']=df.iloc[:,0:10].var(axis=1)
df['标准差']=df.iloc[:,0:10].std(axis=1)
df['均值']=df.iloc[:,0:10].mean(axis=1)
df['变异系数']=df['标准差']/df['均值']
print(df[['方差','标准差','均值','变异系数']].head())
方差 标准差 均值 变异系数
Jack 335.333333 18.312109 85.0 0.215437
Naccy 248.222222 15.755070 93.0 0.169409
Tomi 1011.066667 31.797275 100.8 0.315449
Kattle 560.677778 23.678635 113.3 0.208991
11、分位数
随机生成指定均值及标准差的数组
均值为80,标准差1000,100个元素
np.random.seed(555)
data=np.random.normal(90,1000,100)
columns=['利润']
df=pd.DataFrame(data=data,columns=columns)
print(df)
利润
0 -56.774406
1 -1343.007872
2 658.478778
3 407.370812
4 1290.539436
.. ...
95 -3576.267673
96 1284.847912
97 1569.018945
98 1278.106102
99 1049.559337
[100 rows x 1 columns]
计算25%的分位数,Q1,下四分位数
Q1=df['利润'].quantile(0.24)
print(Q1)
-542.3386271093215
计算75%的分位数,Q3,上四分位数
Q3=df['利润'].quantile(0.75)
print(Q3)
692.4430331948065
计算四分位距,Q3-Q1
IQR=Q3-Q1
print(IQR)
1234.7816603041279
异常值检测
设定上限值和下限值
#其中1.6可以根据需要修改
UPPER=min(Q3+1.5*IQR,df['利润'].max()) #上限值,不超过最大值
LOWER=max(Q1-1.6*IQR,df['利润'].min()) #下限值,不低于最小值
print(UPPER,LOWER)
2174.18102555976 -2024.076619474275
异常值筛选
print(df[(df['利润']>UPPER)|(df['利润']<LOWER)])
利润
7 2256.545529
25 2416.894447
62 -2118.230038
异常值处理
如高于上限值,则使用上限值替换
如低于下限值,则使用下限值替换
df['利润']=df['利润'].clip(LOWER,UPPER)
print(df)
利润
0 238.227202
1 443.486552
2 -997.249893
3 337.095946
4 -66.839938
.. ...
95 -36.653850
96 203.431994
97 -535.683222
98 -391.692502
99 1276.939141
[100 rows x 1 columns]
第二部分——数据格式化
1、设置小数位数
生成6行6列【0,1】的随机小数
df=pd.DataFrame(data=np.random.rand(6,6),columns=['A','B','C','D','E','F']
)
print(df)
A B C D E F
0 0.703276 0.020948 0.755919 0.312978 0.808907 0.072837
1 0.832452 0.995199 0.573117 0.835724 0.981039 0.377530
2 0.862992 0.175143 0.643384 0.110856 0.672894 0.675056
3 0.123777 0.896252 0.610486 0.857352 0.837408 0.112052
4 0.725446 0.987884 0.768086 0.684260 0.880781 0.241966
5 0.932446 0.970043 0.071334 0.110754 0.492671 0.944227
Process finished with exit code 0
所有列保留2位小数
df=df.round(2)
print(df)
A B C D E F
0 0.30 0.37 0.17 0.96 0.05 0.21
1 0.94 0.74 0.59 0.12 0.71 0.24
2 0.70 0.00 0.93 0.23 0.86 0.86
3 0.25 0.71 0.18 0.85 0.21 0.05
4 0.89 0.66 0.09 0.33 0.70 0.57
5 0.33 0.39 0.51 0.45 0.58 0.29
使用字典方法
A列保留1位小数
B列保留2位小数
C列保留3位小数
df=df.round({'A':1,'B':2,'C':3})
print(df)
A B C D E F
0 0.3 0.79 0.433 0.422624 0.193395 0.079944
1 0.7 0.63 0.439 0.615931 0.579699 0.392220
2 0.6 0.05 0.375 0.728126 0.153049 0.197247
3 0.4 0.46 0.090 0.476563 0.362623 0.075163
4 0.7 0.85 0.696 0.028924 0.118933 0.190631
5 0.8 0.62 0.505 0.249056 0.806962 0.765460
使用Series方法
D列保留1位小数
E列保留2位小数
s=pd.Series(index=['D','E'],data=[1,2])
df=df.round(s)
print(df)
A B C D E F
0 0.688167 0.680285 0.410834 0.5 0.87 0.797225
1 0.474939 0.895610 0.177849 0.6 0.38 0.199889
2 0.660301 0.826223 0.908934 0.1 0.52 0.143962
3 0.222549 0.791479 0.014419 0.7 0.75 0.650300
4 0.698036 0.480037 0.160434 0.6 0.53 0.518551
5 0.698345 0.032979 0.828199 0.9 0.14 0.691112
2、设置百分比
2.1apply方法
Series和DataFrame对象均有此方法
指定列保留0位小数的百分比
df['A']=df['A'].apply(lambda x:'{:.0%}'.format(x))
print(df)
A B C D E F
0 84% 0.104631 0.392883 0.871928 0.736681 0.449409
1 60% 0.093204 0.928749 0.363283 0.816510 0.396380
2 55% 0.374437 0.687595 0.292583 0.049900 0.359861
3 98% 0.460631 0.585251 0.759302 0.944639 0.663374
4 44% 0.916017 0.332631 0.976293 0.381050 0.588755
5 60% 0.575272 0.308977 0.689059 0.621878 0.529442
指定列保留2位小数的百分比
df['B']=df['B'].apply(lambda x:'{:.2%}'.format(x))
print(df)
A B C D E F
0 84% 10.46% 0.392883 0.871928 0.736681 0.449409
1 60% 9.32% 0.928749 0.363283 0.816510 0.396380
2 55% 37.44% 0.687595 0.292583 0.049900 0.359861
3 98% 46.06% 0.585251 0.759302 0.944639 0.663374
4 44% 91.60% 0.332631 0.976293 0.381050 0.588755
5 60% 57.53% 0.308977 0.689059 0.621878 0.529442
所有列保留2位小数的百分比(for循环+apply)
df=df.apply(lambda x:'{:.2%}'.format(x),axis=1) # apply解决不了多列格式化,但是可以多列计算
print(df)
TypeError: unsupported format string passed to Series.__format__
print(df)
df=df.apply(lambda x:x*2,axis=1)
print(df)
A B C D E F
0 0.945136 0.747479 0.356623 0.383637 0.883472 0.313727
1 0.430748 0.065730 0.143969 0.947620 0.954460 0.699261
2 0.459772 0.005240 0.343194 0.106431 0.167850 0.802250
3 0.122977 0.844678 0.031901 0.356847 0.961423 0.496245
4 0.819872 0.025313 0.276800 0.696224 0.522683 0.880862
5 0.578156 0.516660 0.875554 0.151881 0.797124 0.994623
A B C D E F
0 1.890273 1.494959 0.713246 0.767275 1.766944 0.627453
1 0.861496 0.131460 0.287938 1.895240 1.908920 1.398522
2 0.919545 0.010480 0.686387 0.212863 0.335701 1.604500
3 0.245955 1.689355 0.063802 0.713695 1.922845 0.992490
4 1.639744 0.050626 0.553600 1.392449 1.045365 1.761723
5 1.156312 1.033319 1.751109 0.303762 1.594248 1.989245
for循环+apply实现
tb=df.copy()
for col in tb.columns:tb[col]=tb[col].apply(lambda x:'{:.2%}'.format(x))
print(tb)
A B C D E F
0 48.32% 17.31% 84.97% 80.69% 26.02% 71.75%
1 54.33% 50.36% 30.39% 48.26% 51.13% 16.52%
2 32.61% 7.00% 44.62% 77.72% 74.05% 44.90%
3 15.93% 87.80% 3.59% 16.55% 46.66% 0.53%
4 60.12% 7.81% 71.37% 2.68% 5.36% 4.94%
5 54.01% 76.41% 22.16% 13.34% 65.07% 48.00%
2.2map方法
DataFrame对象的方法,单列、多列均可支持
所有列保留2位小数的百分比
df=df.map(lambda x:'{:.2%}'.format(x)) #所有列
# df['A']=df['A'].map(lambda x:'{:.1%}'.format(x)) #特定列
print(df)
A B C D E F
0 44.37% 89.32% 62.30% 72.96% 70.20% 39.99%
1 54.85% 70.08% 31.82% 68.16% 62.46% 13.09%
2 45.75% 79.48% 85.74% 69.41% 13.99% 37.70%
3 72.98% 99.24% 43.07% 76.45% 71.15% 11.01%
4 42.68% 69.67% 84.52% 82.42% 9.70% 19.26%
5 42.28% 60.12% 0.09% 99.13% 15.81% 95.51%
map字典操作,字段值映射
td=pd.DataFrame(data=[[1,185],[0,163]],columns=['性别','身高'])
print(td)
dct={1:'男',0:'女'}
td['性别']=td['性别'].map(dct)
print(td)
性别 身高
0 1 185
1 0 163
性别 身高
0 男 185
1 女 163
3、设置千分位符
生成10行6列【1000,10000】的随机整数
df=pd.DataFrame(data=np.random.randint(1000,10000,[10,6]),columns=['A','B','C','D','E','F']
)
print(df)#指定列生成千位分隔符
df['A']=df['A'].apply(lambda x:'{:,}'.format(x)) #转换后为字符串
print(df['A'])
A B C D E F
0 5427 2066 3823 5821 3471 3017
1 3421 1494 7483 2266 7877 5479
2 7939 2223 7856 7586 2908 5103
3 2283 2266 8735 5894 2428 6030
4 2758 2412 8886 6996 7365 2639
5 6041 8076 7496 6898 6077 5961
6 1647 7972 8460 5180 4814 2481
7 7946 7761 1149 7925 1496 9784
8 6900 2639 7381 4164 4163 2192
9 9973 5798 7060 1939 3152 7747
0 5,427
1 3,421
2 7,939
3 2,283
4 2,758
5 6,041
6 1,647
7 7,946
8 6,900
9 9,973
Name: A, dtype: object
所有列设置千位分隔符
df=df.map(lambda x:'{:,}'.format(x))
print(df)
A B C D E F
0 5,924 2,293 7,274 7,737 4,667 6,574
1 1,359 5,615 2,188 7,833 3,789 8,660
2 2,214 5,482 6,206 7,925 6,298 1,714
3 6,499 6,458 3,674 1,260 8,968 8,414
4 3,936 7,443 3,498 3,127 7,530 2,118
5 3,375 1,857 4,436 5,056 8,591 7,177
6 5,098 1,097 3,106 9,680 2,652 8,269
7 2,064 8,875 2,341 2,379 5,615 7,244
8 1,890 8,783 9,597 4,873 3,226 9,577
9 1,208 8,573 1,194 2,948 5,009 9,585
第三部分——数据分组聚合
# filepath='/Users/...'
file1='分组聚合样本集.xlsx'
df=pd.read_excel(filepath+file1,sheet_name='Sheet1')
print(df)
班级id full_channel_code fir_channel ... 数量 金额 利润
0 2379582676258403, RF-IR-APP-PS-NA RF ... 4 80 28
1 5208876134639220, RF-IR-APP-PS-NA RF ... 3 60 13
2 2690764094922305, RF-ZA-CN-NA-NA RF ... 1 20 -17
3 2521134036907050, RF-IR-APP-PS-NA RF ... 3 60 13
4 8110079284895238, RF-ZA-CN-NA-NA RF ... 5 100 43
... ... ... ... ... .. ... ..
5812 1166754878354676, OT-FM-INEN-NA-CNC OT ... 4 80 28
5813 3620708470850021, RF-IR-APP-PS-NA RF ... 4 80 28
5814 8209917189527425, RF-IR-APP-PS-NA RF ... 2 40 -2
5815 1290177434973827, NA-NA-NA-NA-NA NaN ... 5 100 43
5816 7673414805886251, NA-NA-NA-NA-NA NaN ... 1 20 -17
[5817 rows x 9 columns]
1、groupby 分组函数
groupby函数+聚合函数
1.1一列分组一列聚合
print(df.columns)
dt=df.groupby('fir_channel')['数量'].sum().to_frame()
print(dt)
Index(['班级id', 'full_channel_code', 'fir_channel', 'sec_channel', '版本名称', '版本',
'数量', '金额', '利润'],
dtype='object')
数量
fir_channel
12 10
BD 7
MA 4688
MB 12
OT 1994
PM 3014
RF 7484
TT 3
1.2一列分组多列聚合
dt=df.groupby('fir_channel')[['数量','金额']].sum()
print(dt)
数量 金额
fir_channel
12 10 200
BD 7 140
MA 4688 93760
MB 12 240
OT 1994 39880
PM 3014 60280
RF 7484 149680
TT 3 60
1.3多列分组多列聚合
dt=df.groupby(['fir_channel','sec_channel'])[['数量','金额']].sum()
print(dt)
数量 金额
fir_channel sec_channel
12 A- 10 200
BD M- 7 140
MA AM 4 80
AT 14 280
BD 4520 90400
BJ 29 580
OT 121 2420
MB CU 12 240
OT AP 186 3720
CS 90 1800
EL 1 20
FB 35 700
FM 1207 24140
GO 2 40
HK 22 440
LI 27 540
MA 5 100
OT 6 120
SQ 152 3040
VD 7 140
WC 103 2060
WE 44 880
XH 16 320
ZA 86 1720
PM AD 4 80
AM 12 240
BD 5 100
BI 14 280
FB 1452 29040
GG 741 14820
GO 271 5420
HK 8 160
MA 8 160
OT 149 2980
WC 34 680
XH 298 5960
RF AB 28 560
AM 14 280
AT 6 120
BD 5 100
CC 31 620
IR 3858 77160
LA 11 220
OT 32 640
WE 9 180
ZA 3487 69740
2、对分组数据进行遍历
groups=df[['班级id','fir_channel']].groupby('fir_channel')
for key,data in groups:print(key)print(data)print('-'*100)
12
班级id fir_channel
5107 3353791745354775, 12
5125 2728180199386036, 12
----------------------------------------------------------------------------------------------------
BD
班级id fir_channel
1907 4463858807601211, BD
2544 5145806395672121, BD
4420 5812537927831248, BD
----------------------------------------------------------------------------------------------------
MA
班级id fir_channel
17 8503961642095113, MA
29 4369102623668051, MA
30 1149347110468246, MA
31 7400851053228024, MA
34 3942952681187361, MA
... ... ...
5793 8620695404860588, MA
5799 4538518640900089, MA
5800 6597721263080938, MA
5805 8886126326313197, MA
5810 7665451563564088, MA
[1555 rows x 2 columns]
----------------------------------------------------------------------------------------------------
MB
班级id fir_channel
36 8610415545503692, MB
2593 8629038533835623, MB
2594 3513230227082354, MB
2973 4472486190408042, MB
----------------------------------------------------------------------------------------------------
OT
班级id fir_channel
12 6762489426359423, OT
14 7566678849991134, OT
25 5356940618612944, OT
71 5195955925961055, OT
72 5800391234221080, OT
... ... ...
5780 8124923178804172, OT
5785 6627049503215476, OT
5789 8588756983391753, OT
5802 7121606314146451, OT
5812 1166754878354676, OT
[672 rows x 2 columns]
----------------------------------------------------------------------------------------------------
PM
班级id fir_channel
6 1566470936771883, PM
19 2442925164921913, PM
20 3891465133834540, PM
22 4657725897161347, PM
27 7908060522434961, PM
... ... ...
5764 2424033040011328, PM
5786 3565295198791524, PM
5788 7542862051665893, PM
5794 1234455409817918, PM
5795 6370708763461780, PM
[1040 rows x 2 columns]
----------------------------------------------------------------------------------------------------
RF
班级id fir_channel
0 2379582676258403, RF
1 5208876134639220, RF
2 2690764094922305, RF
3 2521134036907050, RF
4 8110079284895238, RF
... ... ...
5807 4375179594793637, RF
5809 8168449201857021, RF
5811 4862988702860130, RF
5813 3620708470850021, RF
5814 8209917189527425, RF
[2490 rows x 2 columns]
----------------------------------------------------------------------------------------------------
TT
班级id fir_channel
2729 1470410680591315, TT
----------------------------------------------------------------------------------------------------
3、groupby+agg函数
3.1指定列使用多个聚合函数
dt=df.groupby('fir_channel').agg({'数量':'mean','金额':'sum'})
print(dt)
数量 金额
fir_channel
12 5.000000 200
BD 2.333333 140
MA 3.014791 93760
MB 3.000000 240
OT 2.967262 39880
PM 2.898077 60280
RF 3.005622 149680
TT 3.000000 60
dt1=df.groupby('fir_channel').agg({'数量':['mean','sum'],'金额':['sum','max']})
print(dt1)
数量 金额
mean sum sum max
fir_channel
12 5.000000 10 200 100
BD 2.333333 7 140 80
MA 3.014791 4688 93760 100
MB 3.000000 12 240 80
OT 2.967262 1994 39880 100
PM 2.898077 3014 60280 100
RF 3.005622 7484 149680 100
TT 3.000000 3 60 60
dt2=df.groupby('fir_channel').agg({'数量':'mean','金额':'max'}).rename(columns={'数量':'数据均值','金额':'金额最大值'})
print(dt2)
数据均值 金额最大值
fir_channel
12 5.000000 100
BD 2.333333 80
MA 3.014791 100
MB 3.000000 80
OT 2.967262 100
PM 2.898077 100
RF 3.005622 100
TT 3.000000 60
dt3=df.groupby('fir_channel').agg(数量均值=('数量','mean'),金额最大值=('金额','max'))
print(dt3)
数量均值 金额最大值
fir_channel
12 5.000000 100
BD 2.333333 80
MA 3.014791 100
MB 3.000000 80
OT 2.967262 100
PM 2.898077 100
RF 3.005622 100
TT 3.000000 60
dt4=df.groupby('fir_channel')['金额'].agg([('销售总额','sum'),('平均金额','mean')])
print(dt4)
销售总额 平均金额
fir_channel
12 200 100.000000
BD 140 46.666667
MA 93760 60.295820
MB 240 60.000000
OT 39880 59.345238
PM 60280 57.961538
RF 149680 60.112450
TT 60 60.000000
4、自定义函数分组统计
统计频数最高(行计数最多)的二级渠道以及总数量和总金额
print(df['sec_channel'].value_counts().index[0])
BD
dt=df.agg({'数量':'sum','金额':'sum','sec_channel':lambda x:x.value_counts().index[0]}).reset_index()
print(dt)
index 0
0 数量 17376
1 金额 347520
2 sec_channel BD
以一级渠道为分组,统计销售数量最多的二级渠道
dt=df[df['fir_channel']=='RF'].groupby('sec_channel')['数量'].sum().idxmax()
print(dt)
IR
print(df.info())
df1=df[df['sec_channel'].notnull()]
print(df1.info())grouped=df1.groupby('fir_channel') # grouped 数据类型是DataFrameGroupBy,没法直接再次用groupby
dt1=grouped.apply(lambda x:x.groupby('sec_channel')['数量'].sum().idxmax())
print(dt1)
由于数据集存在一些二级渠道是空的情况,groupby的时候无索引会报错,剔除之后再处理
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5817 entries, 0 to 5816
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 班级id 5817 non-null object
1 full_channel_code 5817 non-null object
2 fir_channel 5767 non-null object
3 sec_channel 5755 non-null object
4 版本名称 5817 non-null object
5 版本 5817 non-null object
6 数量 5817 non-null int64
7 金额 5817 non-null int64
8 利润 5817 non-null int64
dtypes: int64(3), object(6)
memory usage: 409.1+ KB
None
<class 'pandas.core.frame.DataFrame'>
Index: 5755 entries, 0 to 5814
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 班级id 5755 non-null object
1 full_channel_code 5755 non-null object
2 fir_channel 5755 non-null object
3 sec_channel 5755 non-null object
4 版本名称 5755 non-null object
5 版本 5755 non-null object
6 数量 5755 non-null int64
7 金额 5755 non-null int64
8 利润 5755 non-null int64
dtypes: int64(3), object(6)
memory usage: 449.6+ KB
None
fir_channel
12 A-
BD M-
MA BD
MB CU
OT FM
PM FB
RF IR
dtype: object
5、groupby+transform函数
pd.DataFrame.transform()
统计各版本的金额及占所属大版本的比例
tb=df.groupby(['版本名称','版本']).agg({'金额':'sum'}).reset_index()
print(tb.head())tb['大版本金额']=tb.groupby('版本')['金额'].transform('sum')
print(tb.head())tb['版本金额占比']=tb['金额']/tb['大版本金额']
tb['版本金额占比']=tb['版本金额占比'].map(lambda x:'{:.2%}'.format(x))
print(tb.head(10))
版本名称 版本 金额
0 启蒙版 P3(试听课) 启蒙 69540
1 启蒙版LTO试听课 启蒙 2820
2 拓展版 P1 拓展 2140
3 拓展版 P2 拓展 5840
4 拓展版 P3 试听课 拓展 21740
版本名称 版本 金额 大版本金额
0 启蒙版 P3(试听课) 启蒙 69540 72360
1 启蒙版LTO试听课 启蒙 2820 72360
2 拓展版 P1 拓展 2140 36540
3 拓展版 P2 拓展 5840 36540
4 拓展版 P3 试听课 拓展 21740 36540
版本名称 版本 金额 大版本金额 版本金额占比
0 启蒙版 P3(试听课) 启蒙 69540 72360 96.10%
1 启蒙版LTO试听课 启蒙 2820 72360 3.90%
2 拓展版 P1 拓展 2140 36540 5.86%
3 拓展版 P2 拓展 5840 36540 15.98%
4 拓展版 P3 试听课 拓展 21740 36540 59.50%
5 拓展版25分钟P1试听课 拓展 5520 36540 15.11%
6 拓展版LTO试听课 拓展 1300 36540 3.56%
7 新加坡同步课 P1 新加 17320 20840 83.11%
8 新加坡版LTO试听课 新加 3520 20840 16.89%
9 标准版 LTO试听课 标准 3160 107540 2.94%
6、多列合并计算
6.1 groupby+字典+聚合函数
df1=df.pivot_table(index='sec_channel',columns='版本',values='数量',aggfunc='sum').reset_index()
df1.columns.name=None #去掉透视表的column名称
print(df1.head())
sec_channel 启蒙 拓展 新加 标准 进阶
0 A- 5.0 NaN NaN NaN 5.0
1 AB NaN 2.0 3.0 14.0 9.0
2 AD NaN NaN NaN NaN 4.0
3 AM NaN 6.0 NaN 3.0 21.0
4 AP 50.0 30.0 13.0 49.0 44.0
#合并启蒙、拓展、新加
dct={'启蒙':'启拓新','拓展':'启拓新','新加':'启拓新','标准':'标进','进阶':'标进'
}
#先设置行索引
df1=df1.set_index('sec_channel')
print(df1.head())# df2=df1.groupby(dct,axis=1).sum() #老的写法,新版本将替换为使用T处理
df2=df1.T.groupby(dct).sum().T
print(df2.head())
启拓新 标进
sec_channel
A- 5.0 5.0
AB 5.0 23.0
AD 0.0 4.0
AM 6.0 24.0
AP 93.0 93.0
6.2 groupby+Series+聚合函数
series=pd.Series(data=['启拓新','启拓新','启拓新','标进','标进'],index=['启蒙','拓展','新加','标准','进阶'])df1=df1.set_index('sec_channel')
# df2=df1.groupby(series,axis=1).sum() #原始方法是这样,在将来的版本中会报错
df2=df1.T.groupby(series).sum().T
print(df2.head())
7、pivot_table透视表
# pd.pivot_table(
# data, ——> df对象
# values=None, ——>Excel数据透视表的值
# index=None, ——> 数据透视表的行
# columns=None, ——> 数据透视表的列
# aggfunc='mean', ——> 数据透视表的计算类型
# fill_value=None, ——> 填充空值
# margins=False, ——> 是否显示合计
# dropna=True, ——> 是否删除缺失值(如整行缺失)
# margins_name='All', ——> 合计的别名
# observed=False,
# )
tb=pd.pivot_table(data=df,index='版本',columns='fir_channel',values='金额',aggfunc='sum',margins=True,margins_name='合计')
tb=tb.reset_index()
tb.columns.name=None
print(tb)
版本 12 BD MA MB OT PM RF TT 合计
0 启蒙 100.0 40.0 23960.0 NaN 6680.0 13040.0 27540.0 NaN 71360
1 拓展 NaN NaN 11620.0 80.0 3980.0 4280.0 16540.0 NaN 36500
2 新加 NaN NaN 4660.0 NaN 2880.0 7860.0 5160.0 NaN 20560
3 标准 NaN NaN 20800.0 40.0 18840.0 22880.0 44040.0 NaN 106600
4 进阶 100.0 100.0 32720.0 120.0 7500.0 12220.0 56400.0 60.0 109220
5 合计 200.0 140.0 93760.0 240.0 39880.0 60280.0 149680.0 60.0 344240
8、crosstab交叉表
# pd.crosstab(
# index, ——> 行索引
# columns, ——> 列索引
# values=None, ——> 聚合字段
# rownames=None, ——> 行索引别名
# colnames=None, ——> 列索引别名
# aggfunc=None, ——> 聚合函数
# margins=False, ——> 是否显示合计
# margins_name: str = 'All', ——> 合计别名
# dropna: bool = True, ——> 是否删除缺失行(如整行缺失)
# normalize=False, ——> 值显示方式(True/all:总计百分比,index:行汇总百分比,columns:列汇总百分比)tb=pd.crosstab(index=df['版本'],columns=df['fir_channel'],values=df['金额'],aggfunc='sum',margins=True,margins_name='合计',normalize='columns' #行汇总百分比# normalize='index' #列汇总百分比)
print(tb)
fir_channel 12 BD MA ... RF TT 合计
版本 ...
启蒙 0.5 0.285714 0.255546 ... 0.183993 0.0 0.207297
拓展 0.0 0.000000 0.123933 ... 0.110502 0.0 0.106031
新加 0.0 0.000000 0.049701 ... 0.034474 0.0 0.059726
标准 0.0 0.000000 0.221843 ... 0.294228 0.0 0.309668
进阶 0.5 0.714286 0.348976 ... 0.376804 1.0 0.317279
9、category数据类型
主要为了提升运算性能
用astype把object对象转换为category类型,可以提升运算性能,如groupby
第四部分——数据偏移与切分
1、数据偏移
1.1shift函数
销量增长率=(本期销量-上期销量)/上期销量