0
点赞
收藏
分享

微信扫一扫

python数据分析基础02——pandas相关操作

英乐 2022-02-07 阅读 85

文章目录

pandas高级操作

import pandas as pd
import numpy as np
from pandas import DataFrame

替换操作

  • 替换操作可以同步作用于Series和DataFrame中

  • 单值替换

    • 普通替换: 替换所有符合要求的元素:to_replace=15,value=‘e’
    • 按列指定单值替换: to_replace={列标签:替换值} value=‘value’
  • 多值替换

    • 列表替换: to_replace=[] value=[]
    • 字典替换(推荐) to_replace={to_replace:value,to_replace:value}
df = DataFrame(data=np.random.randint(0,20,size=(8,5)))
df
01234
017017116
183773
29134193
312301016
4855414
51418213
61468155
72771811
#全局替换
df.replace(to_replace=1,value='one')
01234
017017116
183773
29134193
312301016
4855414
514182one3
61468155
72771811
#多值替换:将多个值替换成指定形式
df.replace(to_replace={1:'one',3:'three'})
01234
017017116
18three77three
2913419three
312three01016
4855414
514182onethree
61468155
72771811
#指定列的替换:字典的key表示指定的列索引,字典的value值就是要替换的元素
df.replace(to_replace={3:17},value='one')
01234
0131014217
11724one9
22310one13
31715191315
41051774
5320013
6680161
7151310618

映射操作

  • 概念:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定(给一个元素值提供不同的表现形式)

  • 创建一个df,两列分别是姓名和薪资,然后给其名字起对应的英文名

dic = {
    'name':['张三','李四','王五','张三'],
    'salary':[5000,6000,5500,5000]
}
df = DataFrame(data=dic)
df
namesalary
0张三5000
1李四6000
2王五5500
3张三5000
#映射关系表
dic = {
    '李四':'Jerry',
    '王五':'Jack',
    '张三':'Tom'
}
e_name = df['name'].map(dic)
df['e_name'] = e_name
df
namesalarye_name
0张三5000Tom
1李四6000Jerry
2王五5500Jack
3张三5000Tom
  • map是Series的方法,只能被Series调用

运算工具

  • 超过3000部分的钱缴纳50%的税,计算每个人的税后薪资
def after_sal(s):
    return s - (s-3000)*0.5
after_salary = df['salary'].map(after_sal)
df['after_salary'] = after_salary
df
namesalarye_nameafter_salary
0张三5000Tom4000.0
1李四6000Jerry4500.0
2王五5500Jack4250.0
3张三5000Tom4000.0
  • Series的方法apply也可以像map一样充当运算工具
    • apply充当运算工具效率要远远高于map
def after_sal(s):
    return s - (s-3000)*0.5
after_salary = df['salary'].apply(after_sal)
after_salary
0    4000.0
1    4500.0
2    4250.0
3    4000.0
Name: salary, dtype: float64

排序实现的随机抽样

  • take()
  • np.random.permutation(n):返回0-(n-1)之间的随机序列
df = DataFrame(data=np.random.random(size=(100,3)),columns=['A','B','C'])
df.head()
ABC
00.4438350.9733310.626923
10.3666190.2250350.719683
20.4316390.1542590.051419
30.4069940.0650480.145229
40.9658490.3857880.208316
#将行打乱
df.take(np.random.permutation(100),axis=0)
ABC
880.8821210.3683320.158629
960.3190080.2515460.009901
280.6964310.1784690.125718
230.2680100.6396620.137387
220.5998990.0895350.930574
............
500.4689520.5628390.671872
790.2375260.2280430.699325
870.9321470.3942110.540368
900.9804010.8234020.624730
920.6991010.1080880.542962

100 rows × 3 columns

#将行列打乱
df.take(np.random.permutation(100),axis=0).take(indices=np.random.permutation(3),axis=1)
BAC
460.2741980.6898430.119163
60.4935730.8547490.134710
550.5728230.1590190.124300
650.9824990.8229220.788931
50.5783930.9044010.866710
............
300.7340580.9480660.029316
590.1030370.7483190.025966
480.9880170.1948010.162126
800.5943850.4716180.945606
700.7501100.5925280.470297

100 rows × 3 columns

#将行列打乱,然后进行随机抽样
df.take(np.random.permutation(100),axis=0).take(indices=np.random.permutation(3),axis=1)[0:5]
ABC
380.6057190.8432360.339796
320.7795120.9445510.109526
700.2433080.7996650.374344
370.9291030.9073240.259208
210.9630180.8689060.874337

数据的分类处理

  • 数据分类处理的核心:

    • groupby()函数
    • groups属性查看分组情况
df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'],
                'price':[4,3,3,2.5,4,2],
               'color':['red','yellow','yellow','green','green','green'],
               'weight':[12,20,50,30,20,44]})
df
itempricecolorweight
0Apple4.0red12
1Banana3.0yellow20
2Orange3.0yellow50
3Banana2.5green30
4Orange4.0green20
5Apple2.0green44
df.groupby(by='item')#返回了DataFrameGroupBy对象,分组的结果都存储在了该对象中
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fea8c556460>
#groups查看分组详情
df.groupby(by='item').groups
{'Apple': [0, 5], 'Banana': [1, 3], 'Orange': [2, 4]}
#计算每种水果的平均价格
df.groupby(by='item').mean()
df.groupby(by='item').mean()['price'] #不推荐:浪费了算力
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64
df.groupby(by='item')['price'].mean()#推荐方式
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64
#多个分组条件
df.groupby(by=['item','color'])
df.groupby(by=['color','item']).sum()
priceweight
coloritem
greenApple2.044
Banana2.530
Orange4.020
redApple4.012
yellowBanana3.020
Orange3.050
#需求:计算出每种水果的平均价格,然后将平均价格汇总到原始的表格中
mean_price_s = df.groupby(by='item')['price'].mean()
mean_price_s
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64
dic = mean_price_s.to_dict() #映射关系表
df['mean_price'] = df['item'].map(dic)
df
itempricecolorweightmean_price
0Apple4.0red123.00
1Banana3.0yellow202.75
2Orange3.0yellow503.50
3Banana2.5green302.75
4Orange4.0green203.50
5Apple2.0green443.00
#每种颜色水果的平均重量
mean_weight_s = df.groupby(by='color')['weight'].mean()
dic = mean_weight_s.to_dict()
mean_weight = df['color'].map(dic)
df['mean_weight'] = mean_weight
df
itempricecolorweightmean_pricemean_weight
0Apple4.0red123.0012.000000
1Banana3.0yellow202.7535.000000
2Orange3.0yellow503.5035.000000
3Banana2.5green302.7531.333333
4Orange4.0green203.5031.333333
5Apple2.0green443.0031.333333

高级数据聚合

  • 使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算
  • df.groupby(‘item’)[‘price’].sum() <==> df.groupby(‘item’)[‘price’].apply(sum)
  • transform和apply都会进行运算,在transform或者apply中传入函数即可
  • transform和apply也可以传入一个lambda表达式
def my_mean(p):
    sum = 0
    for i in p:
        sum += i
    return sum / len(p)
# 每种水果的平均价格值,不需要做映射就可汇总到原始表
df.groupby(by='item')['price'].transform(my_mean)
0    3.00
1    2.75
2    3.50
3    2.75
4    3.50
5    3.00
Name: price, dtype: float64
# 每种水果的平均价格值,需要做映射才能汇总到原始表
df.groupby(by='item')['price'].apply(my_mean)
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64

数据加载

  • 读取type-.txt文件数据
df = pd.read_csv('./data/type-.txt')
df
你好-我好-他也好
0也许-大概-有可能
1然而-未必-不见得
df = pd.read_csv('./data/type-.txt',sep='-')
df
你好我好他也好
0也许大概有可能
1然而未必不见得
df = pd.read_csv('./data/type-.txt',sep='-',header=None)
df
012
0你好我好他也好
1也许大概有可能
2然而未必不见得
#\s+表示一个或者多个空格
df = pd.read_csv('./data/test.txt',sep='\s+',header=None)
df
012
0你好我好他也好
1也许大概有可能
2然而未必不见得
#修改列索引
df.columns = ['a','b','c']
df
abc
0你好我好他也好
1也许大概有可能
2然而未必不见得
df.rename(index={0:'a1',1:'a2',2:'a3'})
abc
a1你好我好他也好
a2也许大概有可能
a3然而未必不见得
#参数names可以在读取数据的时候直接修改列索引
df = pd.read_csv('./data/test.txt',sep='\s+',header=None,names=['A','B','C'])
df
ABC
0你好我好他也好
1也许大概有可能
2然而未必不见得

透视表

  • 透视表是一种可以对数据动态排布并且分类汇总的表格格式。或许大多数人都在Excel使用过数据透视表,也体会到它的强大功能,而在pandas中它被称作pivot_table。

  • 透视表的优点:

    • 灵活性高,可以随意定制你的分析计算要求
    • 脉络清晰易于理解数据
    • 操作性强,报表神器
df = pd.read_csv('./data/透视表-篮球赛.csv')
df.head()
对手胜负主客场命中投篮数投篮命中率3分命中率篮板助攻得分
0勇士10230.4350.44461127
1国王8210.3810.2863927
2小牛10190.5260.4623729
3灰熊8200.4000.2505822
476人10200.5000.25031327

pivot_table有四个最重要的参数index、values、columns、aggfunc

  • index参数:分类汇总的分类条件
    • 每个pivot_table必须拥有一个index。如果想查看哈登对阵每个队伍的得分则需要对每一个队进行分类并计算其各类得分的平均值:
df.pivot_table(index='胜负')
3分命中率助攻命中得分投篮命中率投篮数篮板
胜负
0.428199.66666710.23809532.9523810.48152421.1428575.142857
0.293508.5000007.50000027.2500000.35425021.2500004.750000
  • 想看看哈登对阵同一对手在不同主客场下的数据,分类条件为对手和主客场
df.pivot_table(index=['对手','主客场'])
3分命中率助攻命中得分投篮命中率投篮数篮板
对手主客场
76人0.42907.08.029.00.38121.04.0
0.250013.010.027.00.50020.03.0
勇士0.444011.010.027.00.43523.06.0
国王0.28609.08.027.00.38121.03.0
太阳0.54507.012.048.00.54522.02.0
小牛0.46207.010.029.00.52619.03.0
尼克斯0.385010.012.037.00.44427.02.0
0.35309.09.031.00.39123.05.0
开拓者0.57103.016.048.00.55229.08.0
掘金0.14309.06.021.00.37516.08.0
步行者0.333010.08.029.00.36422.08.0
0.250015.09.026.00.42921.05.0
湖人0.44409.013.036.00.59122.04.0
灰熊0.33958.09.530.00.42022.54.5
0.36107.57.524.50.38319.54.5
爵士0.875013.019.056.00.76025.02.0
0.33303.08.029.00.42119.05.0
猛龙0.273011.08.038.00.32025.06.0
篮网0.61508.013.037.00.65020.010.0
老鹰0.545011.08.029.00.53315.03.0
骑士0.429013.08.035.00.38121.011.0
鹈鹕0.400017.08.026.00.50016.01.0
黄蜂0.400011.08.027.00.44418.010.0
  • values参数:需要对计算的数据进行筛选
    • 如果我们只需要哈登在主客场和不同胜负情况下的得分、篮板与助攻三项数据:
df.pivot_table(index=['主客场','胜负'],values=['得分','篮板','助攻'])
助攻得分篮板
主客场胜负
10.55555634.2222225.444444
8.66666729.6666675.000000
9.00000032.0000004.916667
8.00000020.0000004.000000
  • Aggfunc参数:设置我们对数据聚合时进行的函数操作

    • 当我们未设置aggfunc时,它默认aggfunc='mean’计算均值。
  • 还想获得james harden在主客场和不同胜负情况下的总得分、总篮板、总助攻时:

df.pivot_table(index=['主客场','胜负'],values=['得分','篮板','助攻'],aggfunc='sum')
助攻得分篮板
主客场胜负
9530849
268915
10838459
8204
df.pivot_table(index=['主客场','胜负'],aggfunc={'得分':'sum','篮板':'mean','助攻':'min'})
助攻得分篮板
主客场胜负
73085.444444
7895.000000
33844.916667
8204.000000
  • Columns:可以设置列层次字段
    • 对values字段进行分类
#获取所有队主客场的总得分
df.pivot_table(index='主客场',values='得分',aggfunc='sum')
得分
主客场
397
404
#查看主客场下的总得分的组成元素是谁
df.pivot_table(index='主客场',values='得分',aggfunc='sum',columns='对手',fill_value=0)
对手76人勇士国王太阳小牛尼克斯开拓者掘金步行者湖人灰熊爵士猛龙篮网老鹰骑士鹈鹕黄蜂
主客场
29000293702129060563837035260
272727480314802636492900290027

交叉表

  • 是一种用于计算分组的特殊透视图,对数据进行汇总
  • pd.crosstab(index,colums)
    • index:分组数据,交叉表的行索引
    • columns:交叉表的列索引
import pandas as pd
from pandas import DataFrame
df = DataFrame({'sex':['man','man','women','women','man','women','man','women','women'],
               'age':[15,23,25,17,35,57,24,31,22],
               'smoke':[True,False,False,True,True,False,False,True,False],
               'height':[168,179,181,166,173,178,188,190,160]})
df
sexagesmokeheight
0man15True168
1man23False179
2women25False181
3women17True166
4man35True173
5women57False178
6man24False188
7women31True190
8women22False160
  • 求出各个性别抽烟的人数
#分组
df.groupby(by='sex')['smoke'].sum()
#透视
df.pivot_table(index='sex',values='smoke',aggfunc='sum')
smoke
sex
man2
women2
pd.crosstab(df.smoke,df.sex)
sexmanwomen
smoke
False23
True22
pd.crosstab(df.sex,df.smoke)
smokeFalseTrue
sex
man22
women32
  • 求出各个年龄段抽烟人情况
pd.crosstab(df.smoke,df.age)
age151722232425313557
smoke
False001111001
True110000110
举报

相关推荐

0 条评论