pandas数据分析给力教程【完整版】(六)

上一篇:pandas数据分析给力教程【完整版】(五)
下一篇:pandas数据分析给力教程【完整版】(七)

import pandas as pd
from pandas import Series,DataFrame

import numpy as np

pandas数据处理

1、删除重复元素

def make_df(index, cols):
    df = DataFrame({col: [col + str(i) for i in index] for col in cols})
    df.index = index
    return df
df = make_df([1,2,3,4], list('ABCD'))
df
ABCD
1A1B1C1D1
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4

使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True

df.duplicated()
1    False
2    False
3    False
4    False
dtype: bool
df.loc[2] = df.loc[1]
df
ABCD
1A1B1C1D1
2A1B1C1D1
3A3B3C3D3
4A4B4C4D4
df.duplicated(keep='last')
1     True
2    False
3    False
4    False
dtype: bool
df.loc[1, 'D'] = 'D4'
df
ABCD
1A1B1C1D4
2A1B1C1D1
3A3B3C3D3
4A4B4C4D4
df.duplicated(subset=['A', 'B', 'C'])
1    False
2     True
3    False
4    False
dtype: bool

使用drop_duplicates()函数删除重复的行

df.drop_duplicates()
ABCD
1A1B1C1D1
3A3B3C3D3
4A4B4C4D4
df[~df.duplicated()]
ABCD
1A1B1C1D1
3A3B3C3D3
4A4B4C4D4
df[np.logical_not(df.duplicated())]
ABCD
1A1B1C1D1
3A3B3C3D3
4A4B4C4D4

2. 映射

映射的含义:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定

需要使用字典:

map = { 'label1':'value1', 'label2':'value2', ... }

包含三种操作:

  • replace()函数:替换元素
  • 最重要:map()函数:新建一列
  • rename()函数:替换索引

1) replace()函数:替换元素

使用replace()函数,对values进行替换操作

data = np.random.randint(0,150, size=(4,3))
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语']
df = DataFrame(index=index, data=data, columns=columns)
df
语文数学英语
张三11910318
李四510389
王五791132
赵六931432

首先定义一个字典

mapping = {34: 104, 37: 107, 17: 117, 43: 134}

调用.replace()

df.replace(mapping)
语文数学英语
张三9313486
李四1045497
王五11110760
赵六12511738

replace还经常用来替换NaN元素

df.iloc[0,0] = np.nan
df
语文数学英语
张三NaN4386
李四34.05497
王五111.03760
赵六125.01738
df.replace({np.nan: 0})
语文数学英语
张三0.04386
李四34.05497
王五111.03760
赵六125.01738

============================================

练习19:

假设张三李四的课表里有满分的情况,老师认为是作弊,把所有满分的情况(包括150,300分)都记0分,如何实现?

============================================

df.iloc[0,0] = 150
df.iloc[1,0] = 150
df
语文数学英语
张三150.04386
李四150.05497
王五111.03760
赵六125.01738
df.replace({150:  0})
语文数学英语
张三0.04386
李四0.05497
王五111.03760
赵六125.01738

2) map()函数:新建一列

使用map()函数,由已有的列生成一个新列

适合处理某一单独的列。

df
语文数学英语
张三150.04386
李四150.05497
王五111.03760
赵六125.01738
# map的基本用法: 根据已有列的数据来生成新的一列数据
df['理综'] = df['数学'].map({43: 243, 54: 254, 37: 237, 17: 217})
df
语文数学英语理综
张三150.04386243
李四150.05497254
王五111.03760237
赵六125.01738217
# 用法二: 修改已有列的数据
df['数学'] = df['数学'].map({43:143, 54: 124, 37: 137, 17: 117})
df
语文数学英语理综
张三150.014386243
李四150.012497254
王五111.013760237
赵六125.011738217

仍然是新建一个字典

map()函数中可以使用lambda函数

# 用法三: 传递lambda函数
df['及格与否'] = df['英语'].map(lambda item: item >= 60)
df
语文数学英语理综及格与否
张三150.014386243True
李四150.012497254True
王五111.013760237True
赵六125.011738217False
df['python'] = df['英语'].map(lambda item: item * 2)
df
语文数学英语理综及格与否python
张三150.014386243True172
李四150.012497254True194
王五111.013760237True120
赵六125.011738217False76
def convert(item):
    if item >= 80:
        return '优秀'
    elif item >= 60:
        return '及格'
    else:
        return  '不及格'
# map第四个用法: 传递一个普通函数
df['score'] = df['英语'].map(convert)
df
语文数学英语理综及格与否pythonscore
张三150.014386243True172优秀
李四150.012497254True194优秀
王五111.013760237True120及格
赵六125.011738217False76不及格

transform()和map()类似

df['score1'] = df['英语'].transform(convert)
df
语文数学英语理综及格与否pythonscorescore1
张三150.014386243True172优秀优秀
李四150.012497254True194优秀优秀
王五111.013760237True120及格及格
赵六125.011738217False76不及格不及格

使用map()函数新建一个新列

============================================

练习20:

新增两列,分别为张三、李四的成绩状态,如果分数低于90,则为"failed",如果分数高于120,则为"excellent",其他则为"pass"

【提示】使用函数作为map的参数

============================================

3) rename()函数:替换索引

仍然是新建一个字典

df
语文数学英语理综及格与否pythonscorescore1
张三150.014386243True172优秀优秀
李四150.012497254True194优秀优秀
王五111.013760237True120及格及格
赵六125.011738217False76不及格不及格
mapping = {'语文': 'Chinese', '数学': 'Math', '英语': 'English'}
df.rename(mapping, axis=1)
ChineseMathEnglish理综及格与否pythonscorescore1
张三150.014386243True172优秀优秀
李四150.012497254True194优秀优秀
王五111.013760237True120及格及格
赵六125.011738217False76不及格不及格
df.rename(columns=mapping)
ChineseMathEnglish理综及格与否pythonscorescore1
张三150.014386243True172优秀优秀
李四150.012497254True194优秀优秀
王五111.013760237True120及格及格
赵六125.011738217False76不及格不及格
df.rename(index={'张三': 'Mr Zhang', '李四': 'Mr Lee', '王五': 'Lao Wang', '赵六': 'Mr Six'})

语文数学英语理综及格与否pythonscorescore1
Mr Zhang150.014386243True172优秀优秀
Mr Lee150.012497254True194优秀优秀
Lao Wang111.013760237True120及格及格
Mr Six125.011738217False76不及格不及格

使用rename()函数替换行索引

3. 异常值检测和过滤

使用describe()函数查看每一列的描述性统计量

df.describe()
语文数学英语理综python
count4.000004.0000004.0000004.000004.000000
mean134.00000130.25000070.250000237.75000140.500000
std19.3390811.87083326.51257615.5214953.025151
min111.00000117.00000038.000000217.0000076.000000
25%121.50000122.25000054.500000232.00000109.000000
50%137.50000130.50000073.000000240.00000146.000000
75%150.00000138.50000088.750000245.75000177.500000
max150.00000143.00000097.000000254.00000194.000000

使用std()函数可以求得DataFrame对象每一列的标准差

根据每一列的标准差,对DataFrame元素进行过滤。

借助any()函数, 测试是否有True,有一个或以上返回True,反之返回False

对每一列应用筛选条件,去除标准差太大的数据

删除特定索引df.drop(labels,inplace = True)

============================================

练习21:

新建一个形状为10000*3的标准正态分布的DataFrame(np.random.randn),去除掉所有满足以下情况的行:其中任一元素绝对值大于3倍标准差

============================================

异常值的检测一定要有一个标准.具体的标准要根据具体业务来分析.
df = DataFrame(data=np.random.randn(10000,3))
df.head()
012
00.7029581.0769570.300606
10.0781240.0715520.182246
21.121916-1.3799860.489360
30.633601-0.8646420.015258
4-1.379120-0.583192-0.290505
df.std()
0    1.002128
1    0.991692
2    1.002605
dtype: float64
df[~(df.abs() > 3 * df.std()).any(axis=1)]
012
00.7029581.0769570.300606
10.0781240.0715520.182246
21.121916-1.3799860.489360
30.633601-0.8646420.015258
4-1.379120-0.583192-0.290505
50.618883-1.104339-0.570237
60.916081-0.1083720.460898
70.2141170.860870-0.205388
8-0.2534030.1426031.670119
9-0.905850-0.1963222.690032
100.384971-0.0809580.679500
11-0.8071320.5888660.415264
12-0.763031-1.7967800.573219
13-0.274970-1.2885991.230828
14-0.5719520.724518-1.341576
15-1.159281-1.4434611.321074
161.6320150.523967-0.416220
17-0.951032-1.109964-1.268240
18-0.2581330.240632-0.534827
190.4590250.6661120.292500
20-0.3495530.329076-1.036976
210.7047630.487110-0.474845
22-0.8620900.241097-0.348680
230.926968-0.8243180.215676
24-0.9746200.478644-0.227909
250.2713251.4969100.335745
260.6090250.1870040.656713
28-2.3128730.0491480.195795
291.1147681.2298430.165681
301.4989700.5907420.324432
............
99690.671424-0.4162640.068488
99701.167870-0.4097071.541785
99712.202169-0.4273421.890037
99720.977254-0.203149-0.179609
99730.3441810.905022-0.519217
99741.4402560.690965-0.847224
9975-1.4234681.2556300.067692
99762.1316771.7291570.073778
9977-0.8591710.497846-0.212514
9979-2.4100430.2712820.518025
9980-0.0857600.5831190.586410
99811.713973-0.0686641.032057
9982-1.700565-0.126339-0.129507
9983-0.129577-0.5139980.437219
99842.381347-1.657040-0.227971
9985-0.775950-1.122079-1.177830
99860.7067690.0224411.624407
9987-1.490968-0.9598550.185482
9988-0.4509411.0176651.622394
99890.3801560.5123971.219214
99901.132431-0.374839-0.475572
99910.2716831.430147-0.285015
9992-1.276515-0.6823120.557811
99930.0845780.518161-0.441114
99940.5692010.6742690.249646
99951.2494580.809205-0.215635
99961.021031-0.480514-0.971789
99970.1139550.090411-0.825068
99980.870587-1.327828-0.097523
9999-0.8675610.149689-1.583496

9930 rows × 3 columns

1, 先指定异常值检测的标准. <绝对值大于三倍的标准偏差>
2, 把标准写成一个条件.   <df.abs() > 3 * df.std()>
3, 再看是过滤行还是列.  (df.abs() > 3 * df.std()).any(axis=1)
4, 最后再通过中括号中写条件写法把异常值过滤掉.

4. 抽样

使用.take()函数排序

可以借助np.random.permutation()函数随机排序

df
语文数学英语
张三11910318
李四510389
王五791132
赵六931432
df.take([3,2,1,0])
语文数学英语
赵六931432
王五791132
李四510389
张三11910318
df.take([2,1,0], axis=1)
英语数学语文
张三18103119
李四891035
王五321179
赵六321493

随机抽样

# 无放回抽样
np.random.permutation([0,1,2,3])
array([0, 3, 1, 2])
# permutation和take结合可以实现无放回抽样
df.take(np.random.permutation([0,1,2,3]))
语文数学英语
李四510389
赵六931432
张三11910318
王五791132

当DataFrame规模足够大时,直接使用np.random.randint()函数,就配合take()函数实现随机抽样

# 有放回抽样
# np.random.randint和take结合实现有放回抽样
df.take(np.random.randint(0,4, size=4))
语文数学英语
王五791132
王五791132
赵六931432
赵六931432

============================================
练习22:

假设有张三李四王老五的期中考试成绩ddd2,对着三名同学随机排序

============================================

# 无放回抽样
df.take(np.random.permutation([0,1,2,3])[:3])
语文数学英语
王五791132
李四510389
赵六931432
# 有放回抽样
df.take(np.random.randint(0,4, size=4)[:3])
语文数学英语
赵六931432
王五791132
王五791132

5. 数据聚合【重点】

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

数据分类处理:

  • 分组:先把数据分为几组
  • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来

数据分类处理的核心:
groupby()函数

如果想使用color列索引,计算price1的均值,可以先获取到price1列,然后再调用groupby函数,用参数指定color这一列

df = DataFrame({'color':['red','white','red','cyan','cyan','green','white','cyan'],
                'price':np.random.randint(0,8,size = 8),
                'weight':np.random.randint(50,55,size = 8)})
df
colorpriceweight
0red354
1white351
2red650
3cyan350
4cyan053
5green651
6white552
7cyan050
df.groupby(by='color')
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000000001145F710>

使用.groups属性查看各行的分组情况:

df.groupby(by='color').groups
{'cyan': Int64Index([3, 4, 7], dtype='int64'),
 'green': Int64Index([5], dtype='int64'),
 'red': Int64Index([0, 2], dtype='int64'),
 'white': Int64Index([1, 6], dtype='int64')}
# 分组之后 进行聚合
# 先聚合再取值
df.groupby(by='color').sum()[['price']]
price
color
cyan3
green6
red9
white8
#  先取值,再聚合 推荐写法.
price_sum = df.groupby(by='color')[['price']].sum()
df
colorpriceweight
0red354
1white351
2red650
3cyan350
4cyan053
5green651
6white552
7cyan050
df.merge(price_sum, left_on='color', right_index=True, suffixes=['', '_sum'])
colorpriceweightprice_sum
0red3549
2red6509
1white3518
6white5528
3cyan3503
4cyan0533
7cyan0503
5green6516

数据聚合的步骤

1, 分组, 找到分组的列

2, 聚合, 执行聚合操作,sum, mean, max, min

3, 合并, 把聚合的结果合并到原始表中.

============================================

练习23:

假设菜市场张大妈在卖菜,有以下属性:

菜品(item):萝卜,白菜,辣椒,冬瓜

颜色(color):白,青,红

重量(weight)

价格(price)

  1. 要求以属性作为列索引,新建一个ddd
  2. 对ddd进行聚合操作,求出颜色为白色的价格总和
  3. 对ddd进行聚合操作,求出萝卜的所有重量(包括白萝卜,胡萝卜,青萝卜)以及平均价格
  4. 使用merge合并总重量及平均价格

============================================

ddd = DataFrame({'item': ['萝卜', '萝卜','萝卜', '白菜', '白菜','辣椒','辣椒','辣椒', '冬瓜', '冬瓜'], 
                          'color': ['白', '红', '青', '青', '白', '青', '红', '白',  '青', '白'],
                          'weight': [60, 70, 40, 50, 60, 100, 80, 20, 200, 150],
                          'price': [2.68, 3.98, 4.98, 1.28, 1.58, 7.98, 8.88, 12.28, 1.28, 1.58]
                          })
ddd
itemcolorweightprice
0萝卜602.68
1萝卜703.98
2萝卜404.98
3白菜501.28
4白菜601.58
5辣椒1007.98
6辣椒808.88
7辣椒2012.28
8冬瓜2001.28
9冬瓜1501.58
ddd.groupby(by='color')[['price']].sum()
price
color
18.12
12.86
15.52
weight_sum = ddd.groupby(by='item')[['weight']].sum()
price_mean = ddd.groupby(by='item')[['price']].mean()
price_mean
price
item
冬瓜1.430000
白菜1.430000
萝卜3.880000
辣椒9.713333
ddd = ddd.merge(weight_sum, left_on='item', right_index=True, suffixes=['', '_sum'])
ddd.merge(price_mean, left_on='item', right_index=True, suffixes=['', '_mean'])
itemcolorweightpriceweight_sumprice_mean
0萝卜602.681703.880000
1萝卜703.981703.880000
2萝卜404.981703.880000
3白菜501.281101.430000
4白菜601.581101.430000
5辣椒1007.982009.713333
6辣椒808.882009.713333
7辣椒2012.282009.713333
8冬瓜2001.283501.430000
9冬瓜1501.583501.430000

6.0 高级数据聚合

可以使用pd.merge()函数将聚合操作的计算结果添加到df的每一行
使用groupby分组后调用加和等函数进行运算,让后最后可以调用add_prefix(),来修改列名

price_mean = price_mean.add_prefix('mean_')
# 添加后缀
price_mean = price_mean.add_suffix('_mean')
ddd.merge(price_mean, left_on='item', right_index=True)
itemcolorweightpriceweight_sumprice_mean
0萝卜602.681703.880000
1萝卜703.981703.880000
2萝卜404.981703.880000
3白菜501.281101.430000
4白菜601.581101.430000
5辣椒1007.982009.713333
6辣椒808.882009.713333
7辣椒2012.282009.713333
8冬瓜2001.283501.430000
9冬瓜1501.583501.430000

可以使用transform和apply实现相同功能

在transform或者apply中传入函数即可

ddd.groupby(by='item').transform(sum)
colorweightpriceweight_sum
0白红青17011.64510
1白红青17011.64510
2白红青17011.64510
3青白1102.86220
4青白1102.86220
5青红白20029.14600
6青红白20029.14600
7青红白20029.14600
8青白3502.86700
9青白3502.86700
ddd.groupby(by='item').apply(sum)
itemcolorweightpriceweight_sum
item
冬瓜冬瓜冬瓜青白3502.86700
白菜白菜白菜青白1102.86220
萝卜萝卜萝卜萝卜白红青17011.64510
辣椒辣椒辣椒辣椒青红白20029.14600

============================================

练习24:

使用transform与apply实现练习23的功能

============================================

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值