编辑
2026-04-01
undefined
00

目录

缺失值处理
找到缺失值
行过滤
列过滤
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 许可协议。转载请注明出处!