编辑
2026-04-01
undefined
00
请注意,本文编写于 39 天前,最后修改于 33 天前,其中某些信息可能已经过时。

目录

缺失值处理
找到缺失值
行过滤
列过滤
dropna()
填充空值
重复值处理
异常值处理
行列操作
添加行
删除行
添加列
删除列
数据合并
pd.concat()
merge()
数据映射
元素替换
map()函数
apply()函数
transform()函数
修改索引
数据筛选
抽样
分组聚合
分箱操作

在了解完pandas的两种主要数据结构Series序列DataFrame数据框,下面就来学习下pandas是怎么处理数据的。

处理数据一般分为几个阶段:数据整理与清洗、数据分析与建模、数据可视化,pandas是处理数据的理想工具。

缺失值处理

None是Python中自带的空对象。None不能参与任何计算,object类型的运算要比int类型的运算慢得多。

np.nan是浮点类型,能参与到计算中,但计算的结果总是NaN。可以使用np.nan*()函数来计算nan,此时会过滤掉nan。

在pandas中,None与np.nan都视作np.nan。

找到缺失值

找有空的列:df.isnull().any(),any只要有一个为True就为True,类似or。

找不为空的列:df.notnull().all(),all必须全部为True才会是True,类似and。

找有空的行:df.isnull().any(axis=1)

找不为空的行:df.notnull().all(axis=1)

行过滤

cond = df.isnull().any(axis=1) print(df[~cond]) # 或者 cond = df.notnull().all(axis=1) print(df[cond])

列过滤

cond = df.isnull().any() print(df.loc[:, ~cond]) # 或者 cond = df.notnull().all() print(df.loc[:, cond])

dropna()

df.dropna()默认删除有空的行,删除有空的列使用df.dropna(axis=1)。也可以选择过滤的方式,默认how="any",how="all"必须所有数据都为nan才会删除。参数inplace=True会修改原数据。

填充空值

df.fillna(value=100) df.fillna(method="ffill") # 向前填充,向后填充是bfill df.fillna(method="ffill",axis=1) # 向左填充,向右填充是bfill

重复值处理

duplicated()函数用来检测重复行,返回元素为布尔类型的Series对象。

duplicated默认保留重复第一行,keep='last'保留重复最后一行,keep=False不保留重复行。

df.duplicated(keep='first') df.duplicated(subset=["列名"]) # subset参数为列名,对指定列进行去重操作

使用drop_duplicates()函数删除重复行:df.drop_duplicates(subset=["列名"], keep='last')

异常值处理

print(df.describe([0.01, 0.5, 0.99])) # 自定义百分位数 print(df.describe([0.01, 0.5, 0.99]).T) # 行列转置

Series唯一值:print(df[0].unique())

按条件查询:

data = [["Alex", 100, 90], ["Bob", 91, 80], ["Clarke", 82, 88]] df = pd.DataFrame(data, columns=["a", "b", "c"]) print(df.query("b==100")) # 找到 b列=100 所有行 print(df.query("b in [90,100]")) n = 100 print(df.query("b ==@n")) # 使用变量

排序:

print(df.sort_values("b", ascending=False)) # 默认按列名升序排序,ascending=False 降序,axis=1 按行排序 print(df.sort_index(ascending=False)) # 默认按索引升序排序,axis=1 按列索引排序

行列操作

添加行

df = pd.DataFrame([["Alex", 100, 90], ["Bob", 91, 80], ["Clarke", 82, 88]]) df2 = pd.DataFrame([["Dick", 99, 77]]) df3 = pd.concat([df, df2], ignore_index=True) # 默认上下合并 df4 = pd.concat([df, df2], keys=["a", "b"]) # keys添加多层索引

删除行

data = [["Alex", 100, 90], ["Bob", 91, 80], ["Clarke", 82, 88]] df = pd.DataFrame(data) df.drop(1, inplace=True) # 默认删除行 df.drop(1, axis=1, inplace=True) # 删除列 df.drop(index=[1, 2]) # 删除多行 df.drop(columns=[1, 2]) # 删除多列

添加列

data = [["Alex", 100], ["Bob", 91], ["Clarke", 82]] df = pd.DataFrame(data, columns=["Name", "Score_1"]) df.insert(1, column="Score_2", value=[90, 80, 88])

删除列

data = [["Alex", 100, 90], ["Bob", 91, 80], ["Clarke", 82, 88]] df = pd.DataFrame(data, columns=["Name", "Score_1", "Score_2"]) del df["Score_1"] # 使用del删除 df.pop("Name") # 使用pop()方法删除

数据合并

pd.concat()

外连接,类似并集,显示所有数据:

def make_df(indexs, columns): """生成DataFrame""" data = [[str(j) + str(i) for j in columns] for i in indexs] df = pd.DataFrame(data, index=indexs, columns=columns) return df df1 = make_df([1, 2, 3, 4], list("ABCD")) df2 = make_df([5, 2, 3, 10], list("BCDE")) df3 = pd.concat([df1, df2])

内连接,类似交集,只连接匹配的项:df3 = pd.concat([df1, df2], join="inner")

merge()

也可以使用merge()合并数据,类似MySQL中表和表合并。merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并。使用merge合并时,会自动根据两者相同column名称的那一列,作为key来进行合并,每一列元素的顺序不要求一致。

有多列名称相同,可指定一列作为连接字段:

df1 = make_df([1, 2, 3], list("ABC")) df2 = make_df([2, 3, 4], list("BCD")) print(df1.merge(df2, on="C"))

可以配合suffixes参数指定冲突列名:

df1 = make_df([1, 2, 3], list("ABC")) df2 = make_df([2, 3, 4], list("BCD")) print(df1.merge(df2, on="C", suffixes=["_df1", "_df2"]))

如果没有相同列名,需使用来指定2个表中的不同列作为连接字段:

df1 = make_df([1, 2, 3], list("ABC")) df2 = make_df([2, 3, 4], list("BD")) print(df1.merge(df2, left_on="B", right_on="B"))

也可以使用行索引作为连接字段:

df1 = make_df([1, 2, 3], list("ABC")) df2 = make_df([2, 3, 4], list("DE")) print(df1.merge(df2, left_index=True, right_index=True))

merge默认是内连接,可以使用how参数指定连接方式:

df1 = make_df([1, 2, 3], list("ABC")) df2 = make_df([2, 3, 4], list("CD")) print(df1.merge(df2, how="outer"))

左连接:how="left",右连接:how="right"。

数据映射

元素替换

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

import pandas as pd import numpy as np data = [{"Name": "Alex", "Age": 12}, {"Name": "Bob", "Age": 16, "Sex": "1"}] df = pd.DataFrame(data) df.replace({np.nan: 0}, inplace=True)

map()函数

map一般用在Series数据结构,不能用于DataFrame,适合处理某一单独列,在map()函数中可以使用lambda。

def fn(sex): if sex == "1": return "男" elif sex == "2": return "女" else: return "" data = [{"Name": "Alex", "Age": 12}, {"Name": "Bob", "Age": 16, "Sex": "1"}] df = pd.DataFrame(data) df["性别"] = df["Sex"].map(fn)

apply()函数

既支持Series,也支持DataFrame。

df["Age"] = df["Age"].apply(lambda x: "成年" if x >= 18 else "未成年") print(df.apply(lambda x: x.max())) # 对每列操作 print(df.applymap(lambda x: x + 100)) # 对所有DataFrame元素操作

transform()函数

既支持Series,也支持DataFrame。

print(df[1].transform([np.sqrt, np.exp])) # 可以执行多项计算 print(df.transform(lambda x: x + 10)) # 处理每一列 print(df.transform(lambda x: x + 10, axis=1)) # 处理每一行

修改索引

替换索引:

data = [{"Name": "Alex", "Age": 12}, {"Name": "Bob", "Age": 16, "Sex": "1"}] df = pd.DataFrame(data) df.rename(index={0: 10}, inplace=True) # 修改行索引名 df.rename(columns={"Name": "姓名"}, inplace=True) # 修改列索引名

重置索引:df.reset_index(inplace=True)

设置索引:df.set_index(keys=["Age"], inplace=True)

数据筛选

data = [["Alex", 100, 90], ["Bob", 91, 80], ["Clarke", 82, 88]] df = pd.DataFrame(data, index=["one", "two", "three"], columns=["A", "B", "C"]) f1 = df.filter(items=["A", "C"]) # 按名称选择列 f2 = df.filter(regex="e$", axis=0) # 按正则表达式选择列索引名以e结尾,axis=0表示对行操作 f3 = df.filter(like="t", axis=0) # 列索引名中含有t的 f4 = df.filter(like="t", axis=0).filter(items="B") # 连续筛选

抽样

使用take()函数排序,借助np.random.permutation()函数随机排序。

无放回抽样:

data = [["Alex", 100, 90], ["Bob", 91, 80], ["Clarke", 82, 88]] df = pd.DataFrame(data, index=["one", "two", "three"], columns=["A", "B", "C"]) print(df.take(np.random.permutation([0, 1, 2])))

有放回抽样:print(df.take(np.random.randint(0, 3, size=6)))

分组聚合

df = pd.DataFrame( { "color": ["red", "red", "blue", "yellow", "blue"], "price": [1, 3, 5, 6, 7], } ) df2 = df.groupby("color").sum() # 先按 color 进行分组,再聚合 print(df2)

分箱操作

分箱操作就是将连续型数据离散化,分为等距分箱和等频分箱。

等距分箱:

data = np.random.randint(0, 100, size=(5, 3)) df = pd.DataFrame(data, columns=["A", "B", "C"]) print(pd.cut(df.A, bins=4)) bins 指定分箱断点。默认是左开右闭,right=False 左闭右开。参数labels指定分箱后分类的标签 print(pd.cut(df.A, bins=[0, 60, 80, 90, 100], right=False, labels=["D", "C", "B", "A"]))

等频分箱:pd.qcut(df.A, q=4, labels=["D", "C", "B", "A"])

本文作者:a

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!