Pandas实战秘籍:轻松驾驭重复值与异常值的处理艺术,让数据清洗更高效!

在这里插入图片描述

1.导包

import numpy as np
import pandas as pd

2.删除重复行

def make_df(indexs,columns):
    data = [[str(j)+str(i) for j in columns] for i in indexs]
    df = pd.DataFrame(data=data,index=indexs,columns=columns)
    return df
  • 使用 duplicated() 函数检测重复的行
    • 返回元素为布尔类型的 Series 对象
    • 每个元素对应一行,如果该行不是第一次出现,则元素为 True
df = make_df([1,2,3,4],list("ABCD"))
df
ABCD
1A1B1C1D1
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4
# 让第一行和第二行值重复
df.loc[1] = df.loc[2]
df
ABCD
1A2B2C2D2
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4
# 判断是否和前面的行重复(第二行和第一行的值重复)
df.duplicated()
1    False
2     True
3    False
4    False
dtype: bool
# 默认保留第一行
df.duplicated(keep="first")
1    False
2     True
3    False
4    False
dtype: bool
# 保留最后一行
df.duplicated(keep="last")
1     True
2    False
3    False
4    False
dtype: bool
# 标记所有的重复行,不保留任何一行
df.duplicated(keep=False)
1     True
2     True
3    False
4    False
dtype: bool
# 行的值不完全一样的情况
df.loc[1,"D"] = "DDD"
df
ABCD
1A2B2C2DDD
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4
df.duplicated()
1    False
2    False
3    False
4    False
dtype: bool
# subset:子集,指定列的值是否重复
df.duplicated(subset=["A","B","C"])
1    False
2     True
3    False
4    False
dtype: bool
  • 使用 drop_duplicates() 函数删除重复的行
# 删除行的值完全一样的情况
df.drop_duplicates()
ABCD
1A2B2C2DDD
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4
# 删除支持列的值相同的行
df.drop_duplicates(subset=["A","B","C"])
ABCD
1A2B2C2DDD
3A3B3C3D3
4A4B4C4D4
# keep:指定保留的行
df.drop_duplicates(subset=["A","B","C"],keep="last")
ABCD
2A2B2C2D2
3A3B3C3D3
4A4B4C4D4

3.映射

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

包含三种操作:

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

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

  • 使用replace()函数,对values进行替换操作
index = ["张三","张三丰","李白","杜甫"]
columns = ["Python","Java","H5","UI"]
data = np.random.randint(0,100,size=(4,4))

df = pd.DataFrame(data=data,index=index,columns=columns)
df
PythonJavaH5UI
张三35354659
张三丰46962548
李白35863432
杜甫17565029
# 替换元素
df.replace({25:50,17:100})
PythonJavaH5UI
张三35354659
张三丰46965048
李白35863432
杜甫100565029

(2)map()函数:适合处理某一单独的列

  • map()函数中可以使用lambda函数
df2 = df.copy()
df2
PythonJavaH5UI
张三35354659
张三丰46962548
李白35863432
杜甫17565029
# map一般用在Series数据结构,不能用于DataFrame
df2["Python"].map({35:35,46:46,17:100})
张三      35
张三丰     46
李白      35
杜甫     100
Name: Python, dtype: int64
# 将Python的每个人的成绩乘以10
df2["Python"].map(lambda x:x*10)
张三     350
张三丰    460
李白     350
杜甫     170
Name: Python, dtype: int64
# 新增一列
df2["Pandas"] = df2["Python"].map(lambda x:x*10)
df2
PythonJavaH5UIPandas
张三35354659350
张三丰46962548460
李白35863432350
杜甫17565029170
# 新增一列:判断Java的成绩是否及格
df2["Java是否及格"] = df2["Java"].map(lambda n:"及格" if n>=60 else "不及格")
df2
PythonJavaH5UIPandasJava是否及格
张三35354659350不及格
张三丰46962548460及格
李白35863432350及格
杜甫17565029170不及格
# 使用普通函数
# 新增一列:判断UI成绩
# <40 不及格
# 40<=n<50 及格
# >=50 优秀

def fn(n):
    if n < 40:
        return "不及格"
    elif n < 50:
        return "及格"
    return "优秀"

df2 ["UI等级"] = df2["UI"].map(fn)
df2
PythonJavaH5UIPandasJava是否及格UI等级
张三35354659350不及格优秀
张三丰46962548460及格及格
李白35863432350及格不及格
杜甫17565029170不及格不及格

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

df3 = df.copy()
df3
PythonJavaH5UI
张三35354659
张三丰46962548
李白35863432
杜甫17565029
# 默认修改行索引名
df3.rename({"张三":"Mr Zhang"})
PythonJavaH5UI
Mr Zhang35354659
张三丰46962548
李白35863432
杜甫17565029
# 修改行索引名
df3.rename(index={"张三":"Mr Zhang"})
PythonJavaH5UI
Mr Zhang35354659
张三丰46962548
李白35863432
杜甫17565029
# 修改列索引名
df3.rename({"Python":"派森"},axis=1)
派森JavaH5UI
张三35354659
张三丰46962548
李白35863432
杜甫17565029
df3.rename(columns={"Python":"派森"})
派森JavaH5UI
张三35354659
张三丰46962548
李白35863432
杜甫17565029
# 重置索引
df3.reset_index()
indexPythonJavaH5UI
0张三35354659
1张三丰46962548
2李白35863432
3杜甫17565029
# 设置行索引
df3.set_index(keys=["H5"])
PythonJavaUI
H5
46353559
25469648
34358632
50175629

(4)apply()函数:既支持 Series,也支持 DataFrame

df = pd.DataFrame(data=np.random.randint(0,10,size=(5,3)),
                  index=list("ABCDE"),
                  columns=["Python","NumPy","Pandas"]
                 )
df
PythonNumPyPandas
A402
B655
C870
D145
E872
# 用于Series,期中x表示Series中的元素
df["Python"].apply(lambda x: True if x>5 else False)
A    False
B     True
C     True
D    False
E     True
Name: Python, dtype: bool
# 用于DataFrame,其中x是DataFrame中某列或某行的Series数据
# 求每一列数据的平均值
df.apply(lambda x:x.mean(),axis=0)
Python    5.4
NumPy     4.6
Pandas    2.8
dtype: float64
# 求每一行数据的平均值
df.apply(lambda x:x.mean(),axis=1)
A    2.000000
B    5.333333
C    5.000000
D    3.333333
E    5.666667
dtype: float64
# 自定义方法
def fn2(x):
    # 平均值和计算
    return (np.round(x.mean(),1),x.count())
df.apply(fn2,axis=1)
A    (2.0, 3)
B    (5.3, 3)
C    (5.0, 3)
D    (3.3, 3)
E    (5.7, 3)
dtype: object
# applymap:DataFrame专有的方法,其中的x是每个元素
df.applymap(lambda x:x + 100)
PythonNumPyPandas
A104100102
B106105105
C108107100
D101104105
E108107102

(5)transform()函数

df = pd.DataFrame(data=np.random.randint(0,10,size=(5,3)),
                  index=list("ABCDE"),
                  columns=["Python","NumPy","Pandas"]
                 )
df
PythonNumPyPandas
A791
B169
C574
D117
E162
# Series中使用transform
# 可以执行多项计算
df["Python"].transform([np.sqrt,np.exp])
sqrtexp
A2.6457511096.633158
B1.0000002.718282
C2.236068148.413159
D1.0000002.718282
E1.0000002.718282
# DataFrame中使用transform
def convert(x):
    if x.mean() > 5:
        return x * 10
    return x * (-10)

# 处理每一列
df.transform(convert)
PythonNumPyPandas
A-7090-10
B-1060-90
C-5070-40
D-1010-70
E-1060-20
# 处理每一行
df.transform(convert, axis=1)
PythonNumPyPandas
A709010
B106090
C507040
D-10-10-70
E-10-60-20

4.异常值检测和过滤

  • describe():查看每一列的描述性统计量
df = pd.DataFrame(data=np.random.randint(0,10,size=(5,3)),
                  index=list("ABCDE"),
                  columns=["Python","NumPy","Pandas"]
                 )
df
PythonNumPyPandas
A012
B781
C615
D284
E667
df.describe()
PythonNumPyPandas
count5.000005.0000005.000000
mean4.200004.8000003.800000
std3.033153.5637062.387467
min0.000001.0000001.000000
25%2.000001.0000002.000000
50%6.000006.0000004.000000
75%6.000008.0000005.000000
max7.000008.0000007.000000
# 自定义百分数
df.describe([0.01,0.3,0.4,0.9,0.99])
PythonNumPyPandas
count5.000005.0000005.000000
mean4.200004.8000003.800000
std3.033153.5637062.387467
min0.000001.0000001.000000
1%0.080001.0000001.040000
30%2.800002.0000002.400000
40%4.400004.0000003.200000
50%6.000006.0000004.000000
90%6.600008.0000006.200000
99%6.960008.0000006.920000
max7.000008.0000007.000000
# 行列转置
df.describe([0.01,0.3,0.4,0.9,0.99]).T
countmeanstdmin1%30%40%50%90%99%max
Python5.04.23.0331500.00.082.84.46.06.66.967.0
NumPy5.04.83.5637061.01.002.04.06.08.08.008.0
Pandas5.03.82.3874671.01.042.43.24.06.26.927.0
  • df.std():可以求得DataFrame对象每一列的标准差
df.std()
Python    3.033150
NumPy     3.563706
Pandas    2.387467
dtype: float64
  • df.drop():删除特定索引
df2 = df.copy()
df2
PythonNumPyPandas
A012
B781
C615
D284
E667
# 默认删除行
df2.drop("A")
PythonNumPyPandas
B781
C615
D284
E667
df2.drop(index="A")
PythonNumPyPandas
B781
C615
D284
E667
# 删除列
df2.drop("Python",axis=1)
NumPyPandas
A12
B81
C15
D84
E67
df2.drop(columns="Python")
NumPyPandas
A12
B81
C15
D84
E67
# 删除多列或多行
df2.drop(columns=["NumPy","Python"])
Pandas
A2
B1
C5
D4
E7
df2.drop(index=["A","B"])
PythonNumPyPandas
C615
D284
E667
# inplace修改原数据
df2.drop(index=["A","B"],inplace=True)
df2
PythonNumPyPandas
C615
D284
E667
  • unique():唯一,去重(只能用于Series一维数组)
# DataFrame没有unique属性,Series调用unique
df["Python"].unique()
array([0, 7, 6, 2])
  • df.query:按条件查询
# 找到Python列中等于6的所有行
df.query("Python == 6")
PythonNumPyPandas
C615
E667
df.query("Python > 6")
PythonNumPyPandas
B781
df.query("Python < 6")
PythonNumPyPandas
A012
D284
# and,&
df.query("Python > 6 and NumPy == 8")
PythonNumPyPandas
B781
df.query("Python > 6 & NumPy == 8")
PythonNumPyPandas
B781
# or,|
df.query("Python > 6 or NumPy == 8")
PythonNumPyPandas
B781
D284
df.query("Python > 6 | NumPy == 8")
PythonNumPyPandas
B781
D284
# in(成员运算符)
df.query("Python in [0,2,7]")
PythonNumPyPandas
A012
B781
D284
# 使用变量@符号
n = 7
df.query("Python == @n")
PythonNumPyPandas
B781
m = [0,2,7]
df.query("Python in @m")
PythonNumPyPandas
A012
B781
D284
  • df.sort_values():根据值排序
  • df.sort_index():根据索引排序
# sort_values:默认按照列名排序,默认升序(常用)
df.sort_values("Python")
PythonNumPyPandas
A012
D284
C615
E667
B781
# ascending:是否升序,默认是True
df.sort_values("Python",ascending=False)
PythonNumPyPandas
B781
C615
E667
D284
A012
# 根据行索引名排序,会把列进行排序(不常用)
df.sort_values("B",axis=1)
PandasPythonNumPy
A201
B178
C561
D428
E766
# 按照索引名排序,默认是对行索引进行排序,默认是升序
df.sort_index(ascending=False)
PythonNumPyPandas
E667
D284
C615
B781
A012
# 按照列索引排序
df.sort_index(ascending=False,axis=1)
PythonPandasNumPy
A021
B718
C651
D248
E676
  • df.info():查看数据信息
# info:常用
df.info()
<class 'pandas.core.frame.DataFrame'>
Index: 5 entries, A to E
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   Python  5 non-null      int32
 1   NumPy   5 non-null      int32
 2   Pandas  5 non-null      int32
dtypes: int32(3)
memory usage: 272.0+ bytes
  • 练习:

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

df = pd.DataFrame(np.random.randn(10000,3))
df
012
0-0.7423361.219393-0.982067
1-0.4323671.697112-0.159940
20.079646-0.234158-0.500751
3-0.106336-0.0333810.645390
4-1.799314-1.511863-1.160497
............
9995-1.4807270.7168630.080706
99960.453228-0.3605981.056758
99971.3655731.1005290.574414
99980.606161-0.111569-0.423250
9999-0.199662-1.0316381.920479

10000 rows × 3 columns

# 过滤掉 大于3陪标准差的行
# 标准差 df.std(),绝对值 df.abs()
# cond:找到每一个元素是否大于3陪标准差
cond = df.abs() > df.std()*3
cond
012
0FalseFalseFalse
1FalseFalseFalse
2FalseFalseFalse
3FalseFalseFalse
4FalseFalseFalse
............
9995FalseFalseFalse
9996FalseFalseFalse
9997FalseFalseFalse
9998FalseFalseFalse
9999FalseFalseFalse

10000 rows × 3 columns

# 找到存在大于3陪标准差的行
cond2 = cond.any(axis=1)
cond2
0       False
1       False
2       False
3       False
4       False
        ...  
9995    False
9996    False
9997    False
9998    False
9999    False
Length: 10000, dtype: bool
# bool值索引,过滤异常值(大于3陪标准差)
df.loc[~cond2]
012
0-0.7423361.219393-0.982067
1-0.4323671.697112-0.159940
20.079646-0.234158-0.500751
3-0.106336-0.0333810.645390
4-1.799314-1.511863-1.160497
............
9995-1.4807270.7168630.080706
99960.453228-0.3605981.056758
99971.3655731.1005290.574414
99980.606161-0.111569-0.423250
9999-0.199662-1.0316381.920479

9925 rows × 3 columns

5.抽样

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

无放回抽样

df2 = pd.DataFrame(data=np.random.randint(0,10,size=(3,3)),
                  index=list("CDE"),
                  columns=["Python","NumPy","Pandas"]
                 )
df2
PythonNumPyPandas
C769
D896
E744
# [1,0,2]对应行索引,行排序
df2.take([1,0,2])
PythonNumPyPandas
D896
C769
E744
# 列排序
df2.take([1,0,2],axis=1)
NumPyPythonPandas
C679
D986
E474
# 随机排列
np.random.permutation([0,1,2])
array([0, 2, 1])
# 无放回抽样:一次随机取出,没有重复值
df2.take(np.random.permutation([0,1,2]))
PythonNumPyPandas
E744
D896
C769

有放回抽样

# 有放回抽样:可能会出现重复值
np.random.randint(0,3,size=5)
array([1, 2, 1, 0, 2])
df2.take(np.random.randint(0,3,size=5))
PythonNumPyPandas
E744
D896
E744
D896
D896
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾飞开源

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值