解构数据的七十二变:Pandas 的 Series 与 DataFrame 织梦术

🌟 哈喽大家好,我是阳光开朗大男孩(๑•̀ㅂ•́)و✧!

🌱 学习新技能没有太晚的开始,现在就是最好的时机!

💡 注意:本文聚焦 Pandas 核心数据结构 Series 和 DataFrame 的基础用法与实战,进阶内容建议搭配官方文档食用更香~

🚀 今天带你从「0」上手 Pandas 数据处理:从环境配置到数据结构创建,再到属性方法实战,手把手教你用 Pandas 高效处理数据,为后续数据分析打下扎实基础!

👍 如果觉得干货满满,欢迎点赞收藏✨ 分享给更多正在学数据分析的小伙伴吧~

 📌引言: 为什么选择Pandas?四大核心优势解析

"NumPy是手术刀,Pandas是急救箱"

手术刀(NumPy):精密的数值计算

急救箱(Pandas):处理现实数据的全套工具

维度NumPy数组Pandas优势对比
索引系统纯数字位置索引支持标签+位置双索引数据定位效率提升300%
数据类型强制统一类型智能推断混合类型真实数据兼容性更佳
对齐机制无自动对齐基于标签自动对齐数据合并错误率降低80%
元数据仅存储数值支持名称/类型等属性数据自解释性更强

 一、🛠️ 环境配置与基础操作

1.1 安装指南 

# Windows/Mac通用安装命令
pip install pandas

# Mac系统备用命令
pip3 install pandas

1.2 标准导入方式

import pandas as pd  # 行业标准简写

二、核心数据结构深度解析 

  • 图解 Series 与 DataFrame 的结构差异

解释

  • DataFrame

    可以把DataFrame看作由Series对象组成的字典,其中key是列名,值是Series

  • Series

    Series和Python中的列表非常相似,但是它的每个元素的数据类型必须相同

  • Pandas中只有列 或者 二维表, 没有行的数据结构(即使是行的数据, 也会通过列的方式展示). 

三、创建DataFrame的三种方式

Series是Pandas中的最基本的数据结构对象,也是DataFrame的列对象或者行对象,series本身也具有行索引。

 Series是一种类似于一维数组的对象,由下面两个部分组成:

  • values:一组数据(numpy.ndarray类型)
  • index:相关的数据行索引标签;如果没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。

1. 自动生成索引

numpy的ndarray => Series对象

    import numpy as np
    import pandas as pd
    
    # 创建numpy.ndarray对象
    n1 = np.array([1, 2, 3])
    print(n1)
    print(type(n1))
    
    # 将上述的 ndarray对象 转成 Series对象
    s1 = pd.Series(data=n1)
    print(s1)
    print(type(s1))

直接传入Python列表, 构建Series对象 

# 这种方式可以创建Series对象, 但是没有指定 行索引值, 默认是: 0 ~ n 
# s2 = pd.Series(data=['乔峰', '男', 33]) 
s2 = pd.Series(['乔峰', '男', 33])         
# data参数名可以省略不写. print(s2) print(type(s2))     
# <class 'pandas.core.series.Series'>

3. 指定索引

传入Python列表,构建Series对象, 并指定行索引 

# s3 = pd.Series(data=['乔峰', '男', 33], index=['name', 'gender', 'age'])         # data参数名可以省略不写.
s3 = pd.Series(['乔峰', '男', 33], index=['name', 'gender', 'age'])         # data参数名可以省略不写.
# s3 = pd.Series(['乔峰', '男', 33], ['name', 'gender', 'age'])         # 参数名可以省略不写.
print(s3)
print(type(s3))     # <class 'pandas.core.series.Series'>

4. 通过元组和字典创建Series对象

# 使用元组
tuple1 = (1, 2, 3)
s1 = pd.Series(tuple1)
print(s1)

# 使用字典 字典中的key值是Series对象的索引值,value值是Series对象的数据值
dict1 = {'A': 1, 'B': 2, 'C': 3}
s2 = pd.Series(dict1)
print(s2)

四、构建 DataFrame 对象的实用技巧

概述

  • DataFrame是一个表格型的==结构化==数据结构,它含有一组或多组有序的列(Series),每列可以是不同的值类型(数值、字符串、布尔值等)。

  • DataFrame是Pandas中的最基本的数据结构对象,简称df;可以认为df就是一个二维数据表,这个表有行有列有索引

  • DataFrame是Pandas中最基本的数据结构,Series的许多属性和方法在DataFrame中也一样适用.

1. 字典方式创建

# 1. 创建字典, 记录数据.
dict_data = {
    'id': [1, 2, 3],
    'name': ['乔峰', '虚竹', '段誉'],
    'age': [33, 29, 21]
}
# 2. 基于上述的字典, 构建df对象.
# df1 = pd.DataFrame(dict_data)  
# df1 = pd.DataFrame(dict_data, index=['A', 'B', 'C'])   # 指定行索引
# index:指定行索引,  columns:指定列名(的顺序), 如果写的列名不存在, 则该列值为 NaN
df1 = pd.DataFrame(dict_data, index=['A', 'B', 'C'], columns=['id', 'age', 'name'])   
# 3. 打印结果.
print(df1)
print(type(df1))    # <class 'pandas.core.frame.DataFrame'>

2. 列表+元组方式创建

# 1. 基于列表 + 元组, 构建数据集.  一个元组 = 一行数据
list_data = [(1, '乔峰', 33), (2, '虚竹', 29), (3, '段誉', 21)]
# 2. 构建df对象.
# df2 = pd.DataFrame(list_data, index=['X', 'Y', 'Z'], columns=['id', 'age', 'name'])  # 以行的方式传入数据, columns是设置: 列名.
df2 = pd.DataFrame(list_data, index=['X', 'Y', 'Z'], columns=['id', 'name', 'age'])  # 以行的方式传入数据, columns是设置: 列名.
# 3. 打印结果.
print(df2)
print(type(df2))

五、深度解析 Series 的常用属性

1. 常用属性介绍

属性说明
loc使用索引值取子集
iloc使用索引位置取子集
dtype或dtypesSeries内容的类型
TSeries的转置矩阵
shape数据的维数
sizeSeries中元素的数量
valuesSeries的值
indexSeries的索引值

2. 代码演示

# 1. 读取 nobel_prizes.csv 文件的内容, 获取df对象. 
df = pd.read_csv('data/nobel_prizes.csv', index_col='id')   
# index_col: 设置表中的某列为 索引列. df.head()       # 默认获取前 5 条数据

 (1)loc属性

first_row = data.loc[941]
print(first_row)        # 获取第一行数据, 但是是以列的方式展示的
print(type(first_row))  # <class 'pandas.core.series.Series'>

(2)iloc属性  

first_row = data.iloc[0] # 使用索引位置获取自己
print(first_row)        # 获取第一行数据, 但是是以列的方式展示的
print(type(first_row))  # <class 'pandas.core.series.Series'>

 (3)dtype 或者 dtypes

print(first_row.dtype)          # 打印Series的元素类型, object表示字符串
print(first_row['year'].dtype)  # 打印Series的year列的元素类型, int64

# 打印Series的year列的元素类型, 该列值为字符串, 字符串没有dtype属性, 所以报错.
print(first_row['firstname'].dtype)  

 (4)shape 和 size属性  

print(first_row.shape)		# 维度
# 结果为: (7,)		因为有7列元素

print(first_row.size)		# 元素个数: 7

 (5)values 属性

print(first_row.values) # 获取Series的元素值

 (6)index属性

print(first_row.index)  # 获取Series的索引

print(first_row.keys()) # Series对象的keys()方法, 效果同上.

 六、掌握 Series 对象的实用方法

1. 常见方法

方法说明
append连接两个或多个Series
corr计算与另一个Series的相关系数
cov计算与另一个Series的协方差
describe计算常见统计量
drop_duplicates返回去重之后的Series
equals判断两个Series是否相同
get_values获取Series的值,作用与values属性相同
hist绘制直方图
isinSeries中是否包含某些值
min返回最小值
max返回最大值
mean返回算术平均值
median返回中位数
mode返回众数
quantile返回指定位置的分位数
replace用指定值代替Series中的值
sample返回Series的随机采样值
sort_values对值进行排序
to_frame把Series转换为DataFrame
unique去重返回数组
value_counts统计不同值数量
keys获取索引值
head查看前5个值
tail查看后5个值

2. 代码演示

# 1. 构建Series对象.
s1 = pd.Series([1, 2, 3, 4, 2, 3], index=['A', 'B', 'C', 'D', 'E', 'F'])
print(s1)
# 2. 演示Series对象的 常用方法. 
print(len(s1))              # 长度: 6
print(s1.size)              # 长度: 6
print(s1.head())            # 默认获取前 5 条
print(s1.head(n=2))         # 指定, 获取前2条

print(s1.tail())            # 默认获取后 5条
print(s1.tail(n=3))         # 指定, 获取后3条

print(s1.keys())            # 获取Series的索引
print(s1.index)             # 获取Series的索引

print(s1.tolist())          # 转列表
print(s1.to_list())         # 效果同上
print(type(s1.tolist()))    # <class 'list'>

print(s1.to_frame())        # 转成df对象
print(type(s1.to_frame()))  # <class 'pandas.core.frame.DataFrame'>

print(s1.describe())        # 查看Series的详细信息, 例如: 最大值, 最小值, 平均值, 标准差等...
print(s1.max())
print(s1.min())
print(s1.mean())
print(s1.std())             # 标准差

print(s1.drop_duplicates()) # 去重, 返回Series对象
print(s1.unique())          # 去重, 返回数组, <class 'numpy.ndarray'>

print(s1.sort_values())                    # 根据 值 排序, 默认: 升序(ascending=True)
print(s1.sort_values(ascending=False))     # 根据 值 排序, 降序

print(s1.sort_index())                     # 根据 索引 排序, 默认: 升序
print(s1.sort_index(ascending=False))      # 根据 索引 排序, 降序

print(s1.value_counts())                   # 统计每个值出现的次数, 类似于: SQL的 group by + count()
s1.hist()                                  # 绘制: 直方图(柱状图)

 七、电影数据分析实战

# 1. 加载数据源, 获取df对象. 
movie_df = pd.read_csv('data/movie.csv') 
movie_df.head()

# 2. 从df对象中, 获取到 Seires对象. 
# direcctor = movie_df.director_name    # 获取: 导演名字 
direcctor = movie_df['director_name']   # 效果同上.  
print(direcctor)
         
 actor_1_fb_likes = movie_df.actor_1_facebook_likes      # 获取主演的facebook点赞数 
print(actor_1_fb_likes)

# 3. 统计不同导演指导的电影数量, 即: 各导演的总数.  
direcctor.value_counts() 
# 4. 统计主演各个点赞数 数量. 即: 1000点赞有几个, 10000点赞有几个 
# actor_1_fb_likes.value_counts()

# 5. 统计有多少空值.  
# direcctor.count()       # 4814, 统计所有的非空值 
# direcctor.shape         # (4916, ), 总量 
len(direcctor.shape)      # 4916
# 6. 打印描述信息 
# 查看描述信息, 例如: 最大值, 最小值, 平均值, 标准差...     
actor_1_fb_likes.describe()       
# 查看描述信息, 因为是: object(字符串类型), 所以信息没那么多.
direcctor.describe()

整合 

# 加载电影数据
movie = pd.read_csv('data/movie.csv')   
movie.head()

# 获取 导演名(列)
director = movie.director_name      # 导演名
director = movie['director_name']   # 导演名, 效果同上
director

# 获取 主演在脸书的点赞数(列)
actor_1_fb_likes = movie.actor_1_facebook_likes # 主演在脸书的点赞数
actor_1_fb_likes.head()

# 统计相关
director.value_counts() # 不同导演的 电影数
director.count()        # 统计非空值(即: 有导演名的电影, 共有多少),  4814 
director.shape          # 总数(包括null值), (4916,)

# 查看详情
actor_1_fb_likes.describe() # 显示主演在脸书点击量的详细信息: 总数,平均值,方差等...
director.describe()         # 因为是字符串, 只显示部分统计信息

八、Series 布尔索引:精准筛选数据

scientists.csv数据集中,列出大于Age列的平均值的具体值,具体步骤如下:

1. 加载并观察数据集

import pandas as pd

df = pd.read_csv('data/scientists.csv')
print(df)
# print(df.head())
# 输出结果如下
                   Name        Born        Died  Age          Occupation
0     Rosaline Franklin  1920-07-25  1958-04-16   37             Chemist
1        William Gosset  1876-06-13  1937-10-16   61        Statistician
2  Florence Nightingale  1820-05-12  1910-08-13   90               Nurse
3           Marie Curie  1867-11-07  1934-07-04   66             Chemist
4         Rachel Carson  1907-05-27  1964-04-14   56           Biologist
5             John Snow  1813-03-15  1858-06-16   45           Physician
6           Alan Turing  1912-06-23  1954-06-07   41  Computer Scientist
7          Johann Gauss  1777-04-30  1855-02-23   77       Mathematicia

# 演示下, 如何通过布尔值获取元素.
bool_values = [False, True, True, False, False, False, True, False]
df[bool_values]

# 输出结果如下
                   Name        Born        Died  Age          Occupation
1        William Gosset  1876-06-13  1937-10-16   61        Statistician
2  Florence Nightingale  1820-05-12  1910-08-13   90               Nurse
6           Alan Turing  1912-06-23  1954-06-07   41  Computer Scientist

2.  基于条件的筛选

  • 计算Age列的平均值
# 获取一列数据 df[列名]
ages = df['Age']
print(ages)
print(type(ages))
print(ages.mean())

# 输出结果如下
0    37
1    61
2    90
3    66
4    56
5    45
6    41
7    77
Name: Age, dtype: int64
<class 'pandas.core.series.Series'>
59.125
  • 输出大于Age列的平均值的具体值
print(ages[ages > ages.mean()])

# 输出结果如下
1    61
2    90
3    66
7    77
Name: Age, dtype: int64

3. 布尔数组直接筛选

# 上述格式, 可以用一行代码搞定, 具体如下
df[ages > avg_age]                  # 筛选(活的)年龄 大于 平均年龄的科学家信息
df[df['Age'] > df.Age.mean()]       # 合并版写法.

九、Series 的运算规则与应用

Series和数值型变量计算时,变量会与Series中的每个元素逐一进行计算;

两个Series之间计算时,索引值相同的元素之间会进行计算;索引值不同的元素的计算结果会用NaN值(缺失值)填充。 

  • Series和数值运算, 数值会和Series的每个值进行运算.
ages_series + 10
ages_series * 2

  • 两个Series之间计算, 如果长度一致, 会按照对应的元素进行逐个计算
ages_series + ages_series

  • 两个Series之间计算, 如果长度不一致, 则对应元素计算, 不匹配的元素用NaN填充
ages_series + pd.Series([1, 10])

  •  Series之间进行计算, 会尽可能依据 索引来计算, 即: 优先计算索引一样的数据.
# 1. 对 源数据(ages_series), 按照 年龄 降序排列, 获取新的Series对象.
rev_series = ages_series.sort_values(ascending=False)
rev_series

# 2. 查看原始Series对象
ages_series

# 3. 具体的计算过程 
ages_series + rev_series

 十、DataFrame常用属性和方法

1. 基础演示

import pandas as pd

# 加载数据集, 得到df对象
df = pd.read_csv('data/scientists.csv')

print('=============== 常用属性 ===============')
# 查看维度, 返回元组类型 -> (行数, 列数), 元素个数代表维度数
print(df.shape)
# 查看数据值个数, 行数*列数, NaN值也算
print(df.size)
# 查看数据值, 返回numpy的ndarray类型
print(df.values)
# 查看维度数
print(df.ndim)
# 返回列名和列数据类型
print(df.dtypes)
# 查看索引值, 返回索引值对象
print(df.index)
# 查看列名, 返回列名对象
print(df.columns)
print('=============== 常用方法 ===============')
# 查看前5行数据
print(df.head())
# 查看后5行数据
print(df.tail())
# 查看df的基本信息
df.info()
# 查看df对象中所有数值列的描述统计信息
print(df.describe())
# 查看df对象中所有非数值列的描述统计信息
# exclude:不包含指定类型列
print(df.describe(exclude=['int', 'float']))
# 查看df对象中所有列的描述统计信息
# include:包含指定类型列, all代表所有类型
print(df.describe(include='all'))
# 查看df的行数
print(len(df))
# 查看df各列的最小值
print(df.min())
# 查看df各列的非空值个数
print(df.count())
# 查看df数值列的平均值
print(df.mean())

2. DataFrame的布尔索引

# 小案例, 同上, 主演脸书点赞量 > 主演脸书平均点赞量的
movie[movie['actor_1_facebook_likes'] > movie['actor_1_facebook_likes'].mean()]

# df也支持索引操作
movie.head()[[True, True, False, True, False]]

3. DataFrame的计算

scientists * 2					# 每个元素, 分别和数值运算
scientists + scientists			# 根据索引进行对应运算
scientists + scientists[:4]		# 根据索引进行对应运算, 索引不匹配, 返回NAN

十一、更改Series和DataFrame对象的 行索引, 列名

Pandas中99%关于DF和Series调整的API, 都会默认在副本上进行修改, 调用修改的方法后, 会把这个副本返回

这类API都有一个共同的参数: inplace, 默认值是False

如果把inplace的值改为True, 就会直接修改原来的数据, 此时这个方法就没有返回值了

1. 设置索引 

(1)读取文件后, 设置行索引 

# 1. 读取数据源文件, 获取 df对象
movie = pd.read_csv('data/movie.csv')
movie.head()

# 2. 设置 movie_tiltle(电影名) 为 行索引
# 在Pandas中, 90%以上的函数, 都是在源数据拷贝一份进行修改, 并返回副本. 而这类函数都有一个特点, 即: 有 inplace参数. 
# 默认 inplace=False, 即: 返回副本, 不修改源数据.   如果inplace=True, 则是直接修改 源数据.
# new_movie = movie.set_index('movie_title')
# new_movie.head()

movie.set_index('movie_title', inplace=True)

# 3. 查看设置后的 movie这个df对象.
movie.head()

(2)读取文件时, 设置行索引

# 1. 读取数据源文件, 获取 df对象, 指定 电影名为 行索引
movie2 = pd.read_csv('data/movie.csv', index_col='movie_title')
movie2.head()

(3)通过reset_index()函数, 可以重置索引

movie2.reset_index(inplace=True)  # 取消设置的 行索引
movie2.head()

 2. 修改行索引 和 列名

# 1. 读取数据源文件, 获取 df对象, 指定 电影名为 行索引
movie = pd.read_csv('data/movie.csv', index_col='movie_title')
movie.head()

(1)rename()函数直接修改

# 2. 获取 前5个列名, 方便稍后修改.
# ['Avatar', 'Pirates of the Caribbean: At World's End', 'Spectre', 'The Dark Knight Rises', 'Star Wars: Episode VII - The Force Awakens']
movie.index[:5]

# 3. 获取 前5个行索引值, 方便稍后修改.
movie.columns[:5]  # ['color', 'director_name', 'num_critic_for_reviews', 'duration', 'director_facebook_likes']

# 4. 具体的修改 列名 和 行索引的动作.
idx_name = {'Avatar': '阿凡达', "Pirates of the Caribbean: At World's End": '加勒比海盗: 直到世界尽头'}
col_name = {'color': '颜色', 'director_name': '导演名'}

movie.rename(index=idx_name, columns=col_name, inplace=True)

# 5. 查看修改后的数据
movie.head()

(2)将 index 和 column属性提取出来, 修改之后, 再放回去

# 1. 从 df中获取 行索引 和 列名的信息, 并转成列表.
idx_list = movie.index.tolist()  # 行索引信息, ['Avatar', "Pirates of the Caribbean: At World's End", 'Spectre', ...]       
col_list = movie.columns.tolist()  # 列名, ['color', 'director_name', 'num_critic_for_reviews', ...]

# 2. 修改上述的 列表(即: 行索引, 列名)信息.
idx_list[0] = '阿凡达'
idx_list[2] = '007幽灵'

col_list[0] = '颜色'
col_list[1] = '导演名'

# 3. 把上述修改后的内容, 当做新的 行索引 和 列名. 
movie.index = idx_list
movie.columns = col_list

# 4. 查看结果.
movie.head()

3. 添加, 删除, 插入列

(1)添加列

# 1. 添加列, 格式为: df['列名'] = 列值
# 新增1列, has_seen = 0, 表示是否看过这个电影. 0: 没看过, 1:看过
movie['has_seen'] = 0

# 新增1列, 总点赞量 = 导演 + 演员的 脸书点赞量
movie['director_actor_facebook_likes'] = movie['director_facebook_likes'] + movie['actor_3_facebook_likes'] + movie[
    'actor_2_facebook_likes'] + movie['actor_1_facebook_likes']

# 2. 查看结果.
movie.head()

(2)删除列 或者 行

# movie.drop('has_seen')  # 报错, 需要指定方式, 按行删, 还是按列删.
# movie.drop('has_seen', axis='columns')    # 按列删
# movie.drop('has_seen', axis=1)            # 按列删, 这里的1表示: 列

movie.head().drop([0, 1])                # 按行索引删, 即: 删除索引为0和1的行

(3)插入列

有点特殊, 没有inplace参数, 默认就是在原始df对象上做插入的.

# insert() 表示插入列.   参数解释: loc:插入位置(从索引0开始计数), column=列名, value=值
# 总利润 = 总收入 - 总预算
movie.insert(loc=1, column='profit', value=movie['gross'] - movie['budget'])
movie.head()

十二、 导入和导出数据

1. 读取数据

# 需求: 导出数据到 /root/output/...
# 细节: 要导出到的目的地目录, 必须存在, 即:  output目录必须存在.
# 格式:  df.to_后缀名(路径)
# 1. 准备原始df对象.
df = pd.read_csv('data/scientists.csv')
df

2. 处理数据

# 2. 对上述的df做操作, 模拟: 实际开发中, 对df对象做处理. 
# 需求: 筛选出 年龄 大于 平均年龄的数据.
new_df = df[df.Age > df.Age.mean()]
new_df 

3. 导出数据

# 3. 把上述的df对象, 写出到目的地中. 
# pickle: 比较适合 存储中间的df数据, 即: 后续要频繁使用的df对象, 可以存储下来. 
# new_df.to_pickle('output/scientists_pickle.pkl')      # pickle文件的后缀名可以是: .p, .pkl, .pickle

# excel, csv等文件, 适合于: 存储最终结果. 
# 注意: 有三个包需要安装一下, 如果你读写excel文件, 但如果你用的是Anaconda, 已经有了, 无需安装.
# new_df.to_excel('output/scientists.xls')                                 # 会把索引列也当做数据, 写出. 
# new_df.to_excel('output/scientists_noindex.xls', index=False, sheet_name='ai20')   # 不导出索引列, 且设置表名. 

# csv(用逗号隔开), tsv(用\t隔开), 适用于 数据共享, 整合等操作. 
# new_df.to_csv('output/scientists.csv')                        # 会把索引列也当做数据, 写出. 
# new_df.to_csv('output/scientists_noindex.csv', index=False)     # 不导出索引列

# 如果每行数据的 各列值之间用逗号隔开是 csv, 用\t隔开是 tsv
new_df.to_csv('output/scientists_noindex.tsv', index=False, sep='\t')     # 不导出索引列

print('导出成功!')

4. 导入数据

# 演示导入

# pickle文件
# pd.read_pickle('output/scientists_pickle.pkl') 

# excel文件
# pd.read_excel('output/scientists.xls')              # 多一列
# pd.read_excel('output/scientists_noindex.xls')      # 正常

# csv文件
# pd.read_csv('output/scientists.csv')                  # 多一列
# pd.read_csv('output/scientists_noindex.csv')          # 正常

pd.read_csv('output/scientists_noindex.tsv', sep='\t')  # 正常

 

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值