接上篇《59、Pandas库中Series对象的操作(二)
上一篇我们讲解了Series对象的运算、函数应用、时间序列操作,以及Series的案例实践。本篇我们来讲解Pandas中DataFrame对象的操作。

一、DataFrame对象的基本概念及特点

在Pandas库中,DataFrame是一种非常重要的数据结构,它以一种表格的形式存储和操作结构化数据。DataFrame对象不仅继承了NumPy数组的强大功能,还提供了更为丰富的数据操作接口,使得数据分析工作变得既高效又便捷。

1、基本概念

DataFrame是Pandas中的一个二维、大小可变、异构的表格型数据结构,具有标记的轴(行和列)。你可以将其想象成一个Excel表格,其中包含了行和列,每列可以是不同的数据类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,这使得数据的检索和操作变得非常灵活。

2、特点

(1)异构性:DataFrame的列可以是不同的数据类型,这是与NumPy数组的主要区别之一。NumPy数组要求所有元素的数据类型必须相同,而DataFrame则没有这个限制。
(2)标签化的轴:DataFrame的轴可以被视为行和列的标签(或索引)。这使得用户可以通过标签来选择数据,而不仅仅是位置。
(3)丰富的操作接口:Pandas为DataFrame提供了大量的方法,用于数据的清洗、转换、聚合、分组以及可视化等操作。这些方法极大地简化了数据分析的流程。
(4)高效的数据处理能力:DataFrame底层使用NumPy库,因此继承了NumPy的高效性能。同时,Pandas还通过内部优化,使得大数据量的处理变得更加迅速和高效。
(5)集成性:Pandas库与Python的其他数据分析和可视化库(如Matplotlib、Seaborn、SciPy等)有着良好的集成性。用户可以方便地将DataFrame对象与这些库结合使用,进行更复杂的数据分析和可视化工作。
(6)易于理解:DataFrame的表格型结构使得数据更加直观和易于理解。对于熟悉Excel等表格软件的用户来说,DataFrame的使用门槛相对较低。

3、应用场景

DataFrame在数据分析、数据挖掘、机器学习等多个领域都有着广泛的应用。无论是处理CSV文件、Excel文件还是SQL数据库中的数据,DataFrame都能提供强大的支持。通过DataFrame,用户可以轻松地进行数据清洗、转换、聚合等操作,为后续的数据分析和建模工作打下坚实的基础。

综上所述,DataFrame是Pandas库中一个非常重要且强大的数据结构,它以其独特的特点和丰富的操作接口,在数据分析领域发挥着不可替代的作用。

二、DataFrame的创建

在Pandas中,DataFrame的创建方式多种多样,可以基于多种数据源来构建。以下详细介绍了几种常见的创建DataFrame的方法。

1、从字典创建DataFrame

(1)使用pd.DataFrame()函数

从字典创建DataFrame是Pandas中最直接的方式之一。字典的键将被用作DataFrame的列名,而字典的值(通常是列表或NumPy数组)则作为列的数据。

import pandas as pd

# 创建一个字典
data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 28, 34],
    '性别': ['男', '女', '男']
}

# 使用pd.DataFrame()函数创建DataFrame
df = pd.DataFrame(data)

print(df)

效果:

(2)设定列索引和行索引

在创建DataFrame时,还可以指定列索引和行索引。如果数据本身包含了一个可以被用作索引的列(如ID),可以在创建DataFrame后设置其为索引。

# 设定行索引  
index = ['ID001', 'ID002', 'ID003']  
df = pd.DataFrame(data, index=index)  
  
# 查看结果  
print(df)  
  
# 如果数据中有可以作为索引的列,可以在创建后设置  
df.set_index('Name', inplace=True)  
print(df)

效果:

注:在Pandas库中,inplace=True是一个参数,它经常出现在修改DataFrame或Series对象的方法中。这个参数的作用是控制修改是否直接在原对象上进行,还是返回一个新的对象。

2、从CSV文件创建DataFrame

(1)使用pd.read_csv()函数

CSV(逗号分隔值)文件是数据分析中常用的数据格式之一。Pandas提供了read_csv()函数来方便地从CSV文件中读取数据并创建DataFrame。
首先我们创建一个csv文件,打开一个记事本,输入下面的内容:

然后保存后,将txt格式直接修改为csv格式,打开看一下效果(用wps打开):

读取代码:

import pandas as pd

# 使用pd.read_csv()读取CSV文件  
df = pd.read_csv('data.csv')  
  
# 查看前几行数据  
print(df.head())

效果:

(2)处理文件路径、分隔符、编码等参数

read_csv()函数提供了多个参数来处理不同格式的CSV文件,如filepath_or_buffer用于指定文件路径,sep或delimiter用于指定字段分隔符(默认为逗号,),encoding用于指定文件编码(如'utf-8')。

# 指定文件路径、分隔符和编码  
df = pd.read_csv('data.csv', sep=';', encoding='utf-8')  
  
# 查看数据  
print(df)

效果:

这里出现这种结果,是因为我们用的是“,”号进行数据列分割,而用“;”分割的话,所有列都被识别为一列了,因为没有“;”符号可分割

3、从其他数据源创建DataFrame(可选)

Pandas不仅支持从字典和CSV文件创建DataFrame,还支持从其他多种数据源读取数据,如Excel文件、SQL数据库等。

(1)Excel文件

按照原来的数据,准备一个xlsx(csv在wps中另存为xlsx):

使用pd.read_excel()函数可以从Excel文件中读取数据。

# 从Excel文件读取数据(先安装openpyxl库)
df = pd.read_excel('data.xlsx', sheet_name='data')  
  
# 查看数据  
print(df)

效果:

(2)SQL数据库

要使用Pandas从SQL数据库读取数据,你通常需要先安装并配置数据库连接库(如sqlite3、pymysql、psycopg2等),然后使用pd.read_sql_query()或pd.read_sql_table()等函数。
这里我们将之前测试SQLite的db数据库,拷贝到测试代码所在的文件夹下,进行连接测试:

import sqlite3
import pandas as pd

# 连接到SQLite数据库
conn = sqlite3.connect("test.db")

# 从数据库中读取数据
query_sql = "select * from users"
df = pd.read_sql_query(query_sql, conn)

# 关闭连接
conn.close()

# 查看数据
print(df)

效果:

注意:以上SQL数据库示例使用的是SQLite,对于其他类型的数据库(如MySQL、PostgreSQL等),你需要安装相应的Python库并修改连接字符串。

三、DataFrame的基本操作

1、查看DataFrame信息

在Pandas中,DataFrame是处理表格数据的主要数据结构,它提供了多种方法来查看数据的基本信息,以便于数据的分析和处理。

● 使用head(), tail()方法

head(n)方法默认返回DataFrame的前5行数据,n参数可以指定返回的行数。这对于快速查看数据的开始部分非常有用。

import pandas as pd  
  
# 假设df是我们从上个xlsx文件中读取的DataFrame  
df = pd.read_excel('data.xlsx')  
  
# 查看前3行数据  
print(df.head(3))

效果:

tail(n)方法则与head()相反,它默认返回DataFrame的最后5行数据,n参数同样可以指定返回的行数。

# 查看最后2行数据  
print(df.tail(2))

效果:

● 使用info(), describe()方法

info()方法提供了DataFrame的简洁摘要,包括列名、每列的非空值数量、数据类型等信息。

# 查看DataFrame的详细信息  
print(df.info())

效果:

describe()方法提供了数值列的统计汇总,包括计数、平均值、标准差、最小值、四分位数和最大值等。对于非数值列,则提供计数、唯一值数量、众数等统计信息。

# 查看数值列的统计信息  
print(df.describe())

效果:

2、索引和切片

在Pandas中,索引是访问DataFrame行和列的关键。

● 使用行标签和列标签进行索引

可以直接通过列名访问单列数据,这会返回一个Series对象。

# 访问'姓名'列  
print(df['姓名'])

效果:

通过行标签(索引)访问单行数据,需要结合.loc[]或.iloc[]。

● 使用.loc[]和.iloc[]进行定位

.loc[]基于标签的索引器,可以接收行标签和列标签的切片器、布尔数组、可调用对象或标签列表。

# 使用.loc[]访问第一行和'姓名', '年龄'列  
print(df.loc[0, ['姓名', '年龄']])  
  
# 访问'姓名'列中索引为0到2的行  
print(df.loc[0:2, '姓名'])

效果:

.iloc[]基于位置的索引器,主要用于通过整数位置选择数据。

# 使用.iloc[]访问前两行和前两列  
print(df.iloc[:2, :2])

效果:

3、选择数据

Pandas提供了灵活的方式来选择DataFrame中的特定数据。

● 选择单列或多列

如前所述,可以通过列名直接选择单列或多列。

● 选择多行或多列的数据子集

使用.loc[]或.iloc[]结合条件表达式或切片来选择多行多列的数据子集。

# 使用.loc[]选择'年龄'大于25的行和所有列  
print(df.loc[df['年龄'] > 25])  

效果:

● 使用布尔索引

布尔索引是一种强大的选择数据的方法,它允许你根据条件来选择满足特定条件的行。

# 选择'年龄'大于25的所有行  
mask = df['年龄'] > 25  
print(df[mask])  
  
# 或者直接在一个表达式中完成  
print(df[df['年龄'] > 25])

效果:

以上便是DataFrame基本操作的概述,结合实例数据可以更直观地理解和应用这些方法。

四、DataFrame的数据清洗

1、处理缺失值

● 检测缺失值

首先,我们需要检测DataFrame中的缺失值。Pandas提供了isnull()或isna()方法来检测缺失值,返回一个与原DataFrame形状相同的布尔型DataFrame,其中缺失值用True表示。

import pandas as pd  
  
# 创建一个包含不同类型数据和缺失值的DataFrame  
data = {  
    '编号': [1, 2, 3, 4, 5, 6],  
    '姓名': ['张三', '李四', '王五', '赵六', '孙七', '张三'],  # 重复值  
    '年龄': [25, 30, np.nan, 22, 35, 25],  # 缺失值  
    '薪资': [50000, 60000, 70000, 80000, np.nan, 50000],  # 缺失值  
    '入职日期': ['2020-01-01', '2021-02-15', '2022-03-01', '2021-04-15', '2020-05-01', '2020-01-01'],  # 日期时间字符串  
    '类别': ['A', 'B', 'A', 'C', np.nan, 'A']  # 分类数据,包含缺失值  
}  

# 将数据字典转换为DataFrame  
df = pd.DataFrame(data)  

# 检测缺失值  
missing_values = df.isnull()  
print(missing_values.head())  # 查看前几行的缺失值情况  
  
# 统计每列缺失值的数量  
missing_counts = missing_values.sum()  
print(missing_counts)

效果:

● 删除含有缺失值的行或列

根据需求,我们可以选择删除含有缺失值的行或列。通常,删除列的做法比较谨慎,因为列往往代表数据的一个重要维度。

# 删除含有缺失值的行  
df_dropped_rows = df.dropna(axis=0)  # axis=0表示行  
print(df_dropped_rows.shape)  # 查看删除后的形状  
  
# 删除含有缺失值的列(慎用)  
df_dropped_cols = df.dropna(axis=1, how='any')  # how='any'表示只要列中有缺失值就删除  
print(df_dropped_cols.shape)

效果:

● 填充缺失值

对于数值型数据,常用均值、中位数或众数来填充缺失值。对于分类数据,可以使用众数或特定值(如"Unknown")来填充。

# 使用均值填充数值型缺失值
print('【使用均值填充数值型缺失值】')
age_mean = df['年龄'].mean()
df['年龄'] = df['年龄'].fillna(age_mean)
print(df)

# 使用中位数填充
print('【使用中位数填充数值型缺失值】')
age_median = df['薪资'].median()
df['薪资'] = df['薪资'].fillna(age_median)
print(df)

# 对于分类数据,使用众数填充(需要额外计算众数)
print('【使用众数填充分类型缺失值】')
mode_val = df['类别'].mode()[0]
df['类别'] = df['类别'].fillna(mode_val)
print(df)

# 使用固定值填充
# df['某字段'].fillna('Unknown', inplace=True)
# print(df)

效果:

2、数据类型转换

● 使用astype()方法进行数据类型转换

astype()方法允许我们将DataFrame中的列转换为指定的数据类型。

# 将字符串类型的列转换为整数类型  
df['int_column'] = df['str_int_column'].astype(int)  
  
# 注意:转换时可能会遇到无法转换的值,这时可以设置errors参数为'ignore'或'coerce'  
# df['int_column'] = df['str_int_column'].astype(int, errors='coerce')  # 'coerce'会将无法转换的值转换为NaN  
  
# 转换失败时的另一种处理方式是先清洗数据
● 转换日期时间类型

Pandas提供了pd.to_datetime()函数来将字符串或其他类型的数据转换为日期时间类型。

# 假设'date_str_column'是包含日期时间字符串的列  
df['date_column'] = pd.to_datetime(df['date_str_column'])  
  
# 查看转换后的数据类型  
print(df['date_column'].dtype)

3、重复值处理

● 检测重复值

duplicated()方法用于检测DataFrame中的重复值,返回一个布尔型Series,表示每行是否是重复行(第一次出现的重复行返回False,之后的重复行返回True)。

# 检测重复值,排除“编号”列
# 使用subset参数来指定除了哪些列之外的其他列都用于检测重复值
duplicates = df.duplicated(subset=df.columns.difference(['编号']))
print('【检测重复值】')
print(duplicates)

# 查看重复值的总数
print('【查看重复值的总数】')
print(duplicates.sum())

效果:

● 删除重复值

drop_duplicates()方法用于删除重复值,返回一个新的DataFrame,其中删除了指定的重复行。

# 删除所有重复的行,保留第一次出现的行
print('【删除所有重复的行,保留第一次出现的行】')
df_no_duplicates = df.drop_duplicates(subset=df.columns.difference(['编号']))

# 或者,指定子集来检测重复值
df_no_duplicates_subset = df.drop_duplicates(subset=['姓名', '年龄', '类别'])

# 查看结果
print(df_no_duplicates.shape)

效果:

至此,我们完成了DataFrame对象的简介、基本操作及数据清洗相关的内容。下一篇我们来继续讲解DataFrame对象的统计分析、可视化以及数据导出与保存相关内容。

转载请注明出处:https://guangzai.blog.csdn.net/article/details/140418261

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐