05-1 pandas数据处理 删除duplicated()、替换replace(),映射map(),重命名rename()、聚合函数、排序take()、分组groupby()

pandas数据处理

文章目录

  • pandas数据处理
    • 1、删除重复元素duplicated()
    • 2. 映射
      • 1) replace()函数:替换元素
        • Series替换操作
        • DataFrame替换操作
      • 2) map()函数:新建一列
      • 3) rename()函数:替换索引
    • 3. 使用聚合操作对数据异常值检测和过滤
    • 4. 排序
        • 使用.take()函数排序
        • 随机抽样
    • 5. 数据分类处理【重点】

1、删除重复元素duplicated()

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

  • 使用drop_duplicates()函数删除重复的行
  • 使用duplicate()函数查看重复的行
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
data = [[100,100,100],[90,90,88],[100,100,100],[90,90,87],[100,100,100]]
columns = ['python','c++','java']
index = list('ABCDE')
df = DataFrame(data=data,index=index,columns=columns)
df
python c++ java
A 100 100 100
B 90 90 88
C 100 100 100
D 90 90 87
E 100 100 100
df.duplicated(keep="first") # 告诉我们 当前行是否重复
# 参数默认是 keep="first" 保留开始的 意思是如果发现很多重复的元素 第一个不算重复的 后面的才是 某一行重复 就返回True
结果为:
A    False
B    False
C     True
D    False
E     True
dtype: bool
df.duplicated(keep="last") # keep last 如果遇到重复的元素 最后一个不算重复的 前面的才算重复 这一行重复了 就是True
结果为:
A     True
B    False
C     True
D    False
E    False
dtype: bool
df.duplicated(keep=False) # 只要有和别人完全一样的 不管在开头还是结尾 都算重复 这一行如果是重复的就返回 True
结果为:
A     True
B    False
C     True
D    False
E     True
dtype: bool
df.drop_duplicates() # {'first', 'last', False}, default 'first'
python c++ java
A 100 100 100
B 90 90 88
D 90 90 87
df.drop_duplicates(keep="last") 
python c++ java
B 90 90 88
D 90 90 87
E 100 100 100
df.drop_duplicates(keep=False) 
python c++ java
B 90 90 88
D 90 90 87

2. 映射

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

包含三种操作:

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

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

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

Series替换操作

  • 单值替换
    • 普通替换
    • 字典替换(推荐)
  • 多值替换
    • 列表替换
    • 字典替换(推荐)
s1 = Series(data = [100,'peppa',np.nan,'chengdu'])
s1
结果为:
0        100
1      peppa
2        NaN
3    chengdu
dtype: objec

单值替换 普通替换

s1.replace(to_replace="peppa",value="佩琪")
结果为:
0        100
1         佩琪
2        NaN
3    chengdu
dtype: object

单值替换 字典替换( )

s1.replace({"chengdu":"成都"})
结果为:
0      100
1    peppa
2      NaN
3       成都
dtype: object

多值替换 列表替换 s1.replace([要替换的值1,要替换的值2,…],[替换成什么1,替换成什么2,…])

s1.replace([100,np.nan],["满分","空值"])
结果为:
0         满分
1      peppa
2         空值
3    chengdu
dtype: object

多值替换 字典替换( { 要替换的值:替换成什么,要替换的值:替换成什么 } )

s1.replace({100:"满分","peppa":"佩琪"})
结果为:
0         满分
1         佩琪
2        NaN
3    chengdu
dtype: object

Series参数说明:

  • method:对指定的值使用相邻的值填充
  • limit:设定填充次数
s2 = Series(data=np.array([80,100,100,100,89,78]))
s2
结果为:
0     80
1    100
2    100
3    100
4     89
5     78
dtype: int32

如果指定value不好 还可以找值来填充

s2.replace(to_replace=100,method="bfill") # 从后面找值来替换当前值
结果为:
0    80
1    89
2    89
3    89
4    89
5    78
dtype: int32
s2.replace(to_replace=100,method="ffill") # 从前面找
结果为:
0    80
1    80
2    80
3    80
4    89
5    78
dtype: int32
s2.replace(to_replace=100,method="ffill",limit=1) # limit 指定是最多往前或者往后找几个, 如果找不到就不填充了 ,limit 默认是None不限制
结果为:
0     80
1     80
2    100
3    100
4     89
5     78
dtype: int32

DataFrame替换操作

  • 单值替换

    • 普通替换
    • 按列指定单值替换{列标签:目标值}
  • 多值替换

    • 列表替换
    • 单字典替换(推荐)
df = pd.read_excel("../data/data.xls",sheet_name=0)
df
0 1 2 3 4
A NaN NaN NaN Beijing
B 69.0 142.0 29 Beijing
C 111.0 7.0 2 Beijing
D 139.0 19.0 125 shanghai
E 12.0 66.0 Beijing shanghai

普通的单值替换

df.replace(to_replace='Beijing',value='北京')
0 1 2 3 4
A NaN NaN NaN 北京
B 69.0 142.0 29 北京
C 111.0 7.0 2 北京
D 139.0 19.0 125 shanghai
E 12.0 66.0 北京 shanghai

按列指定单值换目标值 ({列索引,待替换值},目标值)

df.replace({4:'Beijing'},'首都')
0 1 2 3 4
A NaN NaN NaN 首都
B 69.0 142.0 29 首都
C 111.0 7.0 2 首都
D 139.0 19.0 125 shanghai
E 12.0 66.0 Beijing shanghai

多值替换 列表替换,replace([要替换的1,要替换的2…],[替换成1,替换成2])

df.replace([66,'甲','shanghai'],[100,'first','上海'])
0 1 2 3 4
A first NaN NaN NaN Beijing
B 69.0 142.0 29 Beijing
C 111.0 7.0 2 Beijing
D 139.0 19.0 125 上海
E 12.0 100.0 北京 上海

多值替换 字典替换,replace({要替换的1:替换成的值1,要替换的2:替换成的值2,…}) 可以将没有的值也放在这里 不会报错 将来可以整个项目使用一个过滤器,我们可以在 字典里面写很多值 字典中的值即使找不到也不会报错

df.replace({66:100,'乙':'second','Beijing':'BEIJING','没有的值':'也可以放'})
0 1 2 3 4
A NaN NaN NaN BEIJING
B second 69.0 142.0 29 BEIJING
C 111.0 7.0 2 BEIJING
D 139.0 19.0 125 shanghai
E 12.0 100.0 BEIJING shanghai

注意:DataFrame中,无法使用method和limit参数

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

练习19:

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

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

data = [[150,300],[150,300]]
index = ["张三","李四"]
columns = ["数学","理综"]
df = DataFrame(data,index,columns)
df
数学 理综
张三 150 300
李四 150 300

替换多个

df.replace({150:0,300:0})
df.replace([150,300],[0,0])
数学 理综
张三 0 0
李四 0 0

单值替换

df1 = df.replace(to_replace=150,value=0)
df1 = df.replace({"数学":150},0)
数学 理综
张三 0 300
李四 0 300
df1.replace(to_replace=300,value=0)
df1.replace({"理综":300},0)
数学 理综
张三 0 300
李四 0 300

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

  • map(字典) 字典的键要足以匹配所有的数据,否则出现NaN
  • map()可以映射新一列数据
  • map()中可以使用lambd表达式
  • map()中可以使用方法,可以是自定义的方法

注意 map()中不能使用sum之类的函数,for循环

score = pd.read_excel('./data.xls',sheet_name=1)
score
姓名 语文 数学 python php
0 小明 90 98 90 98
1 小红 44 89 44 89
2 小芳 98 90 90 98
3 小李 89 44 44 89
4 李元芳 78 98 98 87
5 狄仁杰 66 44 44 89

映射字典

map_dic = {'小明':'北京','小红':'上海','小芳':'北京',
 '小李':'广州','李元芳':'成都','狄仁杰':'成都'}

map函数不是DataFrame的方法,而是Sereis对象的方法, 可以传入映射字典

score["姓名"].map(map_dic)
结果为:
0    北京
1    上海
2    北京
3    广州
4    成都
5    成都
Name: 姓名, dtype: object
score["所在城市"] = score["姓名"].map(map_dic) # 可以传入字典
score
姓名 语文 数学 python php 所在城市
0 小明 90 98 90 98 北京
1 小红 44 89 44 89 上海
2 小芳 98 90 90 98 北京
3 小李 89 44 44 89 广州
4 李元芳 78 98 98 87 成都
5 狄仁杰 66 44 44 89 成都

还可以传入 拉姆达表达式 如 lambda x:x+10

score["python"]= score["python"].map(lambda x:x+10)
score        #python数据加10
姓名 语文 数学 python php 所在城市
0 小明 90 98 100 98 北京
1 小红 44 89 54 89 上海
2 小芳 98 90 100 98 北京
3 小李 89 44 54 89 广州
4 李元芳 78 98 108 87 成都
5 狄仁杰 66 44 54 89 成都

还可以传入自定义函数

def fn(x):
    return x-20
score["php"]= score["php"].map(fn) #这里一定要注意,是把函数名传入,千万不要加小括号去调用    
score
姓名 语文 数学 python php 所在城市
0 小明 90 98 100 18 北京
1 小红 44 89 54 9 上海
2 小芳 98 90 100 18 北京
3 小李 89 44 54 9 广州
4 李元芳 78 98 108 7 成都
5 狄仁杰 66 44 54 9 成都
data = np.random.randint(0,150,size=(5,3))
columns = ['python','java','php']
index = ['peppa','mery','tom','jack','rose']
df = DataFrame(data,index,columns)
df
python java php
peppa 23 98 81
mery 33 31 74
tom 59 24 101
jack 56 143 96
rose 94 13 89
def map_score(x):
    if x>120:
        return "exellent"
    elif x<90:
        return "failed"
    else:
        return "pass" 
df["phpx"]= df["php"].map(map_score)
df
python java php phpx
peppa 23 98 81 failed
mery 33 31 74 failed
tom 59 24 101 pass
jack 56 143 96 pass
rose 94 13 89 failed

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

对DataFrame的索引名进行更改,仍然是新建一个字典

score = pd.concat((df,df),keys=['A','B'],axis=1)
score
A B
python java php phpx python java php phpx
peppa 23 98 81 failed 23 98 81 failed
mery 33 31 74 failed 33 31 74 failed
tom 59 24 101 pass 59 24 101 pass
jack 56 143 96 pass 56 143 96 pass
rose 94 13 89 failed 94 13 89 failed
map_dic = {'peppa':'帅气','mery':'美丽','python':'蟒蛇',
  'java':'咖啡','php':'拍黄片','A':'上','B':'下'}         
score.rename(map_dic) # 默认是替换 行的名称
A B
python java php phpx python java php phpx
帅气 23 98 81 failed 23 98 81 failed
美丽 33 31 74 failed 33 31 74 failed
tom 59 24 101 pass 59 24 101 pass
jack 56 143 96 pass 56 143 96 pass
rose 94 13 89 failed 94 13 89 failed
score.rename(columns=map_dic) # 指定columns可以对列名称进行替换
蟒蛇 咖啡 拍黄片 phpx 蟒蛇 咖啡 拍黄片 phpx
peppa 23 98 81 failed 23 98 81 failed
mery 33 31 74 failed 33 31 74 failed
tom 59 24 101 pass 59 24 101 pass
jack 56 143 96 pass 56 143 96 pass
rose 94 13 89 failed 94 13 89 failed
score.rename(columns=map_dic,level=0) # 通过level参数 可以指定具体对哪一层级进行替换  
python java php phpx python java php phpx
peppa 23 98 81 failed 23 98 81 failed
mery 33 31 74 failed 33 31 74 failed
tom 59 24 101 pass 59 24 101 pass
jack 56 143 96 pass 56 143 96 pass
rose 94 13 89 failed 94 13 89 failed
score.rename(columns=map_dic,level=1) # 0 是最外层 
A B
蟒蛇 咖啡 拍黄片 phpx 蟒蛇 咖啡 拍黄片 phpx
peppa 23 98 81 failed 23 98 81 failed
mery 33 31 74 failed 33 31 74 failed
tom 59 24 101 pass 59 24 101 pass
jack 56 143 96 pass 56 143 96 pass
rose 94 13 89 failed 94 13 89 failed
score.rename(columns=map_dic,level=-1)
A B
蟒蛇 咖啡 拍黄片 phpx 蟒蛇 咖啡 拍黄片 phpx
peppa 23 98 81 failed 23 98 81 failed
mery 33 31 74 failed 33 31 74 failed
tom 59 24 101 pass 59 24 101 pass
jack 56 143 96 pass 56 143 96 pass
rose 94 13 89 failed 94 13 89 failed

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

  • index 替换行索引
  • columns 替换列索引
  • level 指定多维索引的维度

3. 使用聚合操作对数据异常值检测和过滤

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

data = np.random.randn(1000,5)
df = DataFrame(data)
df
df.describe() 
0 1 2 3 4
count 1000.000000 1000.000000 1000.000000 1000.000000 1000.000000
mean -0.041642 0.013773 0.014445 0.019873 0.042694
std 1.025455 1.013594 0.983300 1.006718 0.968992
min -2.977845 -3.063590 -3.032535 -2.888868 -3.191746
25% -0.703325 -0.712109 -0.645296 -0.644217 -0.597502
50% -0.054138 0.057187 0.001426 0.020060 0.057830
75% 0.664146 0.704886 0.653665 0.690365 0.725881
max 3.777147 3.113222 3.149599 3.305668 3.050308

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

df.std()
结果为:
0    1.025455
1    1.013594
2    0.983300
3    1.006718
4    0.968992
dtype: float64

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

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

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

# 寻找异常数据 太大的 或者 太小的
df.mean() # 各个列的平均值 是一个Series
df - df.mean() # DataFrame - Series DataFrame中的每一行都和Series做减法 对应的列相减
df - df.mean() > 3*df.std()
(df - df.mean() > 3*df.std()).any()
(df - df.mean() > 3*df.std()).any(axis=1)  #
df[(df - df.mean() > 3*df.std()).any(axis=1)] #找到异常的行

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

drop_idx = df[(df - df.mean() > 3*df.std()).any(axis=1)].index
df.drop(drop_idx).shape

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

练习:

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

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

4. 排序

使用.take()函数排序

  • take()函数接受一个索引列表,用数字表示
  • eg:df.take([1,3,4,2,5])

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

data = np.random.randint(0,100,size=(5,5))
index = list('ABCDE')
columns = list('甲乙丙丁戊')
df = DataFrame(data=data,index=index,columns=columns)
df
A 19 22 59 34 79
B 43 71 71 25 77
C 46 63 43 14 66
D 89 46 86 33 40
E 36 79 66 68 67
df.take([3,2,1]) # 按照索引去取行 顺序随意 还可以重复 还可以不完全
D 89 46 86 33 40
C 46 63 43 14 66
B 43 71 71 25 77
df.take([3,3,3,3]) 
D 89 46 86 33 40
D 89 46 86 33 40
D 89 46 86 33 40
D 89 46 86 33 40
np.random.permutation(5)
结果为:
array([3, 1, 4, 2, 0])
df.take(np.random.permutation(5)) # 随机排序 (行不会少 也不会重复 只是顺序随机变换)
B 43 71 71 25 77
D 89 46 86 33 40
C 46 63 43 14 66
A 19 22 59 34 79
E 36 79 66 68 67

随机抽样

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

df.take(np.random.randint(0,5,size=2)) # 随机抽样
B 43 71 71 25 77
C 46 63 43 14 66

5. 数据分类处理【重点】

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

数据分类处理:

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

数据分类处理的核心:

 - groupby()函数
 - groups属性查看分组情况

In [547]:

df = DataFrame({'item':['苹果','香蕉','橘子','香蕉','橘子','苹果','苹果'],
                'price':[4,3,3,2.5,4,2,2.8],
               'color':['red','yellow','yellow','green','green','green','yello'],
               'weight':[12,20,50,30,20,44,37]})
df        
item price color weight
0 苹果 4.0 red 12
1 香蕉 3.0 yellow 20
2 橘子 3.0 yellow 50
3 香蕉 2.5 green 30
4 橘子 4.0 green 20
5 苹果 2.0 green 44
6 苹果 2.8 yello 37
  • 根据item分组,通过groups属性查看结果
df.groupby("item").groups
结果为:
{'橘子': Int64Index([2, 4], dtype='int64'),
 '苹果': Int64Index([0, 5, 6], dtype='int64'),
 '香蕉': Int64Index([1, 3], dtype='int64')}
  • 获取weight的总和
df.groupby("item")["weight"].sum() #各类水果的总重量
结果为:
item
橘子    70
苹果    93
香蕉    50
Name: weight, dtype: int64
  • 把总和跟df进行merge合并
df2 = DataFrame(df.groupby("item")["weight"].sum())
df2
weight
item
橘子 70
苹果 93
香蕉 50
pd.merge(df,df2,on="item",how="outer",suffixes=["","_total"])
item price color weight weight_total
0 苹果 4.0 red 12 93
1 苹果 2.0 green 44 93
2 苹果 2.8 yello 37 93
3 香蕉 3.0 yellow 20 50
4 香蕉 2.5 green 30 50
5 橘子 3.0 yellow 50 70
6 橘子 4.0 green 20 70

你可能感兴趣的:(05-1 pandas数据处理 删除duplicated()、替换replace(),映射map(),重命名rename()、聚合函数、排序take()、分组groupby())