1、Pandas

在这里插入图片描述

潘哒斯~

Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。

  • 用得最多的pandas对象是Series,一个一维的标签化数组对象,另一个是DataFrame,它是一个面向列的二维表结构。

在这里插入图片描述

1.1、Pandas优点

Numpy已经能够帮助我们处理数据,能够结合matplotlib解决部分数据展示等问题,那么pandas学习的目的在什么地方呢?

  • 增强图表可读性
  • 便捷的数据处理能力
  • 读取文件方便
  • 封装了Matplotlib、Numpy的画图和计算

在这里插入图片描述

# 安装
conda install pandas

2、Pandas数据结构

Pandas中一共有三种数据结构,分别为:

  1. Series:一维数据结构
  2. DataFrame:二维的表格型的数据结构
  3. MultiIndex:三维的数据结构(了解)

2.1、Series

Series是一个类似于一维数组的数据结构,它能够保存任何类型的数据,比如整数、字符串、浮点数等,**主要由一组数据和与之相关的索引两部分构成。**其实类似于Java的Map结构

在这里插入图片描述

2.1.1、Series的创建

# 导入pandas
import pandas as pd

pd.Series(data=None, index=None, dtype=None)

参数:

  • data:传入的数据,可以是ndarray、list等
  • index:索引,必须是唯一的,且与数据的长度相等。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
  • dtype:数据的类型
import pandas as pd

s = pd.Series([4, 7, -5, 3])
print(s)
# 0 4
# 1 7
# 2 -5
# 3 3
# dtype: int64

在这里插入图片描述

Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引

通过已有数据创建:

  • 指定内容,默认索引
# np.arange(10) 生成随机0-10,步长默认为1的数组
pd.Series(np.arange(10))

在这里插入图片描述

  • 指定索引
pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])

在这里插入图片描述

  • 通过字典数据创建
color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
color_count

在这里插入图片描述

2.1.2、Series的属性

属性 说明
index Series的索引对象
values Series的值
ndim Series的维度
shape Series的形状
size Series的元素个数
dtype或dtypes Series的元素类型
name Series的名称
loc[] 显式索引,按标签索引或切片
iloc[] 隐式索引,按位置索引或切片
at[] 使用标签访问单个元素
iat[] 使用位置访问单个元素

为了更方便地操作Series对象中的索引和数据,Series中提供了两个属性index和values

  • 索引index
import numpy as np
# 导入pandas
import pandas as pd

color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
# 查看全部索引
color_count.index

# 查看全部值
color_count.values

在这里插入图片描述

也可以使用索引来获取数据:

在这里插入图片描述

import pandas as pd
arrs = pd.Series([11,22,33,44,55],name="atguigu",index=["a","b","c","d","e"])

# index Series的索引对象
print(arrs.index) # Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

"""
a
b
c
d
e
"""
for i in arrs.index:
  print(i)
# values  Series的值
print(arrs.values)    # [11 22 33 44 55]
# ndim Series的维度
print(arrs.ndim)   # 1维
# shape Series的形状
print(arrs.shape) # (5,)  5行1列
# size Series的元素个数
print(arrs.size)  # 5
# dtype或dtypes Series的元素类型
print(arrs.dtype)
print(arrs.dtypes)
# name Series的名称
print(arrs.name)  # atguigu

在这里插入图片描述

import pandas as pd
arrs = pd.Series([11,22,33,44,55],name="atguigu",index=["a","b","c","d","e"])


# loc[] 显式索引,按标签索引
# 查找索引标签为 "c" 的元素
print(arrs.loc["c"])
# 选取从标签 "c" 到 "d" 的所有元素。[]闭区间
print(arrs.loc["c":"d"])


# iloc[]  隐式索引,按位置索引
# 查找第 0 个位置的元素(即第一个元素)
print(arrs.iloc[0])
# 选取从位置 0 到 3 的元素 [)区间
print(arrs.iloc[0:3])


# 优化版本(使用这个)
# at[] 使用标签访问单个元素
# 查找索引标签为 "a" 的元素
print(arrs.at["a"])
# iat[] 使用位置访问单个元素
# 查找第 3 个位置的元素
print(arrs.iat[3])

在这里插入图片描述

2.1.3、Series的常用方法

方法 说明
head() 查看前n行数据,默认5行
tail() 查看后n行数据,默认5行
isin() 元素是否包含在参数集合中
isna() 元素是否为缺失值(通常为 NaN 或 None)
sum() 求和,会忽略 Series 中的缺失值
mean() 平均值
min() 最小值
max() 最大值
var() 方差
std() 标准差
median() 中位数
mode() 众数(出现频率最高的值),如果有多个值出现的频率相同且都是最高频率,这些值都会被包含在返回的 Series 中
quantile(q,interpolation) 指定位置的分位数q的取值范围是 0 到 1 之间的浮点数或浮点数列表,如quantile(0.5)表示计算中位数(即第 50 百分位数);interpolation:指定在计算分位数时,如果分位数位置不在数据点上,采用的插值方法。默认值是线性插值 ‘linear’,还有其他可选值如 ‘lower’、‘higher’、‘midpoint’、‘nearest’ 等
describe() 常见统计信息
value_count() 每个元素的个数
count() 非缺失值元素的个数,如果要包含缺失值,用len()
drop_duplicates() 去重
unique() 去重后的数组
nunique() 去重后元素个数
sample() 随机采样
sort_index() 按索引排序
sort_values() 按值排序
replace() 用指定值代替原有值
to_frame() 将Series转换为DataFrame
equals() 判断两个Series是否相同
keys() 返回Series的索引对象
corr() 计算与另一个Series的相关系数 默认使用皮尔逊相关系数(Pearson correlation coefficient)来计算相关性。要求参与比较的数组元素类型都是数值型。当相关系数为 1 时,表示两个变量完全正相关,即一个变量增加,另一个变量也随之增加。当相关系数为 -1 时,表示两个变量完全负相关,即一个变量增加,另一个变量随之减少。当相关系数为 0 时,表示两个变量之间不存在线性相关性。例如,分析某地区的气温和冰淇淋销量之间的关系
cov() 计算与另一个Series的协方差
hist() 绘制直方图,用于展示数据的分布情况。它将数据划分为若干个区间(也称为 “bins”),并统计每个区间内数据的频数。需要安装matplotlib包
items() 获取索引名以及值
import pandas as pd
import numpy as np

arrs = pd.Series([11,22,np.nan,None,44,22],index=['a','b','c','d','e','f'])
# head()  查看前n行数据,默认5行
print(arrs.head())
# tail()  查看后n行数据,默认5行
print(arrs.tail(3))
# isin()  判断数组中的每一个元素是否包含在参数集合中
print(arrs.isin([11]))
# isna()  元素是否为缺失值
print(arrs.isna())
# sum() 求和,会忽略 Series 中的缺失值
print(arrs.sum())
# mean()  平均值
print(arrs.mean())
# min() 最小值
print(arrs.min())
# max() 最大值
print(arrs.max())
# var() 方差
print(arrs.var())
# std() 标准差
print(arrs.std())
# print(arrs.var())
# median() 中位数
print(arrs.median())
# mode()  众数
print(arrs.mode())
# quantile()  指定位置的分位数,如quantile(0.5)
print(arrs.quantile(0.25, interpolation="midpoint"))

# describe()  常见统计信息
print(arrs.describe())
# value_counts()  每个元素的个数
print(arrs.value_counts())
# count()  非缺失值元素的个数
print(arrs.count())
print(len(arrs))
print(len(arrs))
# drop_duplicates() 去重 这里可以看出,底层None也作为NaN处理
print(arrs.drop_duplicates())
# unique() 去重后的数组
print(arrs.unique())

# nunique() 去重后元素个数
print(arrs.nunique())
# sample() 随机采样
print(arrs.sample())

# sort_index() 按索引排序
print(arrs.sort_index())

# sort_values() 按值排序
print(arrs.sort_values())
# replace() 用指定值代替原有值
print(arrs.replace(22,"haha"))

# to_frame()  将Series转换为DataFrame
print(arrs.to_frame())

# equals() 判断两个Series是否相同
arr1 = pd.Series([1,2,3])
arr2 = pd.Series([1,2,3])
print(arr1.equals(arr2))
# keys()  返回Series的索引对象
print(arrs.index)
print(arrs.keys())
# corr()  计算与另一个Series的相关系数
arr3 = pd.Series([3,2,1])
arr4 = pd.Series([6,7,8])
arr5 = pd.Series([1, -1, 1, -1])
arr6 = pd.Series([1, 1, -1, -1])
print(arr1.corr(arr2))
print(arr1.corr(arr3))
print(arr1.corr(arr4))
print(arr5.corr(arr6))

# cov() 计算与另一个Series的协方差
print(arr1.corr(arr3))

# hist()  绘制直方图
arr7 = pd.Series([3,2,1,1,1,2,2])
# 绘制直方图
arr7.hist(bins=3)
# items()  获取索引名以及值
for i,v in arr7.items():
  print(i,v)

2.1.4、Series的布尔索引

可以使用布尔索引从Series中筛选满足某些条件的值。

import pandas as pd


s = pd.Series({"a": -1.2, "b": 3.5, "c": 6.8, "d": 2.9})
bools = s > s.mean() # 将大于平均值的元素标记为 True
print(bools) #  打印上一步生成的布尔序列
# a  False
# b   True
# c   True
# d  False
# dtype: bool

# Pandas 会检查 bools 中的每一个值,只保留 s 中对应位置为 True 的元素,而丢弃对应位置为 False 的元素。
print(s[bools]) # 
# b  3.5
# c  6.8
# dtype: float64

在这里插入图片描述

2.1.5、Series的运算

  1. Series与标量运算:标量会与每个元素进行计算
import pandas as pd


s = pd.Series({"a": -1.2, "b": 3.5, "c": 6.8, "d": 2.9})
print(s * 10)
# a  -12.0
# b  35.0
# c  68.0
# d  29.0
# dtype: float64
  1. Series与Series运算:会根据标签索引进行对位计算,索引没有匹配上的会用NaN填充
import pandas as pd


s1 = pd.Series([1, 1, 1, 1])
s2 = pd.Series([2, 2, 2, 2], index=[1, 2, 3, 4])
print(s1 + s2)
# 0  NaN
# 1  3.0
# 2  3.0
# 3  3.0
# 4  NaN
# dtype: float64

在这里插入图片描述

2.2、DataFrame

DataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引

  • 行索引,表明不同行,横向索引,叫index,0轴,axis=0
  • 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
  • 可以把DataFrame看作由Series对象组成的字典,其中key是列名,值是Series

2.2.1、DataFrame的创建

# 导入pandas
import pandas as pd

pd.DataFrame(data=None, index=None, columns=None)
  • 参数:
    • index:行标签。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
    • columns:列标签。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
# np.random.randn(2,3)随机生成2行3列的值
pd.DataFrame(np.random.randn(2,3))

在这里插入图片描述

DataFrame的创建有两种方式:

  1. 直接通过字典创建DataFrame
df = pd.DataFrame({"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [20, 30, 40]})
print(df)
#     id name  age
# 0  101   张三   20
# 1  102   李四   30
# 2  103   王五   40

在这里插入图片描述

  1. 通过字典创建时指定列的顺序和行索引
df = pd.DataFrame(
    data={"age": [20, 30, 40], "name": ["张三", "李四", "王五"]}, columns=["name", "age"], index=[101, 102, 103]
)
print(df)
#     name  age
# 101   张三   20
# 102   李四   30
# 103   王五   40

在这里插入图片描述

举例:创建学生成绩表

# 生成10名同学,5门功课的数据
score = np.random.randint(40, 100, (10, 5))

# 使用Pandas中的数据结构
score_df = pd.DataFrame(score)

在这里插入图片描述

但是这样可读性比较差,我们加上行列索引,显示结果更佳:

# 构造行索引序列
subjects = ["语文", "数学", "英语", "政治", "体育"]

# 构造列索引序列
stu = ['同学' + str(i) for i in range(score_df.shape[0])]

# 添加行索引
data = pd.DataFrame(score, columns=subjects, index=stu)

在这里插入图片描述

2.2.2、DataFrame的属性

属性 说明
index DataFrame的行索引
columns DataFrame的列标签
values DataFrame的值
ndim DataFrame的维度
shape DataFrame的形状
size DataFrame的元素个数
dtypes DataFrame的元素类型
T 行列转置
loc[] 显式索引,按行列标签索引或切片
iloc[] 隐式索引,按行列位置索引或切片
at[] 使用行列标签访问单个元素
iat[] 使用行列位置访问单个元素
import pandas as pd

df = pd.DataFrame(data={"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [20, 30, 40]},index=["aa", "bb", "cc"])
# index DataFrame的行索引
# Index(['aa', 'bb', 'cc'], dtype='object')
print(df.index)

# columns  DataFrame的列标签
# Index(['id', 'name', 'age'], dtype='object')
print(df.columns)


# values  DataFrame的值
"""
[[101 '张三' 20]
 [102 '李四' 30]
 [103 '王五' 40]]
"""
print(df.values)


# ndim DataFrame的维度
print(df.ndim)   # 2
# shape DataFrame的形状
print(df.shape)   # (3, 3)
# size DataFrame的元素个数
print(df.size)
# dtypes  DataFrame的元素类型
"""
id       int64
name    object
age      int64
"""
print(df.dtypes)

# T 行列转置
print(df.T)
# loc[] 显式索引,按行列标签索引或切片
print(df.loc["aa":"cc"])
print(df.loc[:,["id","name"]])
# iloc[]  隐式索引,按行列位置索引或切片
print(df.iloc[0:1])
print(df.iloc[0:3,2])
print("----------")



# at[] 使用行列标签访问单个元素
print(df.at["aa","name"])
# iat[] 使用行列位置访问单个元素
print(df.iat[0,1])

在这里插入图片描述

  • shape:查看是几行几列

在这里插入图片描述

  • index:DataFrame的行索引列表

在这里插入图片描述

  • columns:DataFrame的列索引列表

在这里插入图片描述

  • values:直接获取其中array的值

在这里插入图片描述

  • T:转置

在这里插入图片描述

  • head(5):显示前5行内容.如果不补充参数,默认5行。填入参数N则显示前N行

在这里插入图片描述

  • tail(5):显示后5行内容。如果不补充参数,默认5行。填入参数N则显示后N行

2.2.3、DataFrame的常用方法

方法 说明
head() 查看前n行数据,默认5行
tail() 查看后n行数据,默认5行
isin() 元素是否包含在参数集合中
isna() 元素是否为缺失值
sum() 求和
mean() 平均值
min() 最小值
max() 最大值
var() 方差
std() 标准差
median() 中位数
mode() 众数
quantile() 指定位置的分位数,如quantile(0.5)
describe() 常见统计信息
info() 基本信息
value_counts() 每个元素的个数
count() 非空元素的个数
drop_duplicates() 去重
sample() 随机采样
replace() 用指定值代替原有值
equals() 判断两个DataFrame是否相同
cummax() 累计最大值
cummin() 累计最小值
cumsum() 累计和
cumprod() 累计积
diff() 一阶差分,对序列中的元素进行差分运算,也就是用当前元素减去前一个元素得到差值,默认情况下,它会计算一阶差分,即相邻元素之间的差值。参数:periods:整数,默认为 1。表示要向前或向后移动的周期数,用于计算差值。正数表示向前移动,负数表示向后移动。axis:指定计算的轴方向。0 或 ‘index’ 表示按列计算,1 或 ‘columns’ 表示按行计算,默认值为 0。
sort_index() 按行索引排序
sort_values() 按某列的值排序,可传入列表来按多列排序,并通过ascending参数设置升序或降序
nlargest() 返回某列最大的n条数据
nsmallest() 返回某列最小的n条数据

在Pandas的 DataFrame 方法里,axis 是一个非常重要的参数,它用于指定操作的方向。axis 参数可以取两个主要的值,即 0 或 ‘index’,以及 1 或 ‘columns’ ,其含义如下:

  • axis=0 或 axis=‘index’:表示操作沿着行的方向进行,也就是对每一列的数据进行处理。
  • axis=1 或 axis=‘columns’:表示操作沿着列的方向进行,也就是对每一行的数据进行处理。
import pandas as pd


df = pd.DataFrame(data={"id": [101, 102, 103,104,105,106,101], "name": ["张三", "李四", "王五","赵六","冯七","周八","张三"], "age": [10, 20, 30, 40, None, 60,10]},index=["aa", "bb", "cc", "dd", "ee", "ff","aa"])
# head()  查看前n行数据,默认5行
print(df.head())
# tail()  查看后n行数据,默认5行
print(df.tail())
# isin()  元素是否包含在参数集合中
print(df.isin([103,106]))
# isna()  元素是否为缺失值
print(df.isna())
# sum() 求和
print(df["age"].sum())
# mean()  平均值
print(df["age"].mean())
# min() 最小值
print(df["age"].min())
# max() 最大值
print(df["age"].max())
# var() 方差
print(df["age"].var())
# std() 标准差
print(df["age"].std())
# median() 中位数
print(df["age"].median())
# mode()  众数
print(df["age"].mode())
# quantile()  指定位置的分位数,如quantile(0.5)
print(df["age"].quantile(0.5))
# describe()  常见统计信息
print(df.describe())
# info()  基本信息
print(df.info())
# value_counts()  每个元素的个数
print(df.value_counts())
# count()  非空元素的个数
print(df.count())
# drop_duplicates() 去重
print(df.duplicated(subset="age"))
# sample() 随机采样
print(df.sample())
# replace() 用指定值代替原有值
print("----------------")
print(df.replace(20,"haha"))
# equals() 判断两个DataFrame是否相同
df1 = pd.DataFrame(data={"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [10, 20, 30]})
df2 = pd.DataFrame(data={"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [10, 20, 30]})
print(df1.equals(df2))
# cummax() 累计最大值
df3 = pd.DataFrame({'A': [2, 5, 3, 7, 4],'B': [1, 6, 2, 8, 3]})
# 按列 等价于axis=0 默认
print(df3.cummax(axis="index"))
# 按行 等价于axis=1
print(df3.cummax(axis="columns"))
# cummin() 累计最小值
print(df3.cummin())
# cumsum() 累计和
print(df3.cumsum())
# cumprod() 累计积
print(df3.cumprod())
# diff()  一阶差分
print(df3.diff())
# sort_index() 按行索引排序
print(df.sort_index())
# sort_values() 按某列的值排序,可传入列表来按多列排序,并通过ascending参数设置升序或降序
print(df.sort_values(by="age"))
# nlargest()  返回某列最大的n条数据
print(df.nlargest(n=2,columns="age"))
# nsmallest()  返回某列最小的n条数据
print(df.nsmallest(n=1,columns="age"))

在这里插入图片描述

2.2.4、DataFrame的布尔索引

import pandas as pd


df = pd.DataFrame(
 data={"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"]},
 columns=["name", "age"],
 index=[101, 104, 103, 102],
)
"""
101    False
104     True
103     True
102    False
Name: age, dtype: bool
"""

print(df["age"] > 25)

"""
    name  age
104   李四   30
103   王五   40
"""
print(df[df["age"] > 25])

在这里插入图片描述

2.2.3、DataFrame的更改操作

创建行索引:创建DataFrame时如果不指定行索引,pandas会自动添加从0开始的索引。

import pandas as pd


df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
print(df)
#  age name  id
# 0  20  张三 101
# 1  30  李四 102
# 2  40  王五 103
# 3  10  赵六 104

在这里插入图片描述

  1. 通过set_index()设置行索引

在这里插入图片描述

  1. 通过reset_index()重置行索引
df.reset_index(inplace=True)  # 重置索引
print(df)
#     id  age name
# 0  101   20   张三
# 1  102   30   李四
# 2  103   40   王五
# 3  104   10   赵六

修改行索引名和列名:

  1. 通过rename()修改行索引名和列名
import pandas as pd

df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True)  # 设置id为索引
print(df)
#   age name
# id
# 101  20  张三
# 102  30  李四
# 103  40  王五
# 104  10  赵六

df.rename(
    # 把行索引从数字(101、102...)改为中文 一、二、三、四
    index={101: "一", 102: "二", 103: "三", 104: "四"},
    # 把列名 age 改为 "年龄",name 改为 "姓名"
    columns={"age": "年龄", "name": "姓名"},
    # 同样表示直接修改原 DataFrame
    inplace=True)
print(df)
#   年龄 姓名
# id
# 一  20 张三
# 二  30 李四
# 三  40 王五
# 四  10 赵六

在这里插入图片描述

  1. 将index和columns重新赋值
df.index = ["Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ"]
df.columns = ["年齡", "名稱"]
print(df)
#    年齡  名稱
# Ⅰ  20  张三
# Ⅱ  30  李四
# Ⅲ  40  王五
# Ⅳ  10  赵六
  1. 添加列:通过 df[“列名”] 添加列
import pandas as pd

df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True)  # 设置id为索引
#   age name
# id
# 101  20  张三
# 102  30  李四
# 103  40  王五
# 104  10  赵六
df["phone"] = ["13333333333", "14444444444", "15555555555", "16666666666"]
print(df)

在这里插入图片描述

  1. 删除列:通过 df.drop(“列名”, axis=1) 删除,也可是删除行 axis=0
df.drop("phone", axis=1, inplace=True)  # 删除phone,按列删除,inplace=True表示直接在原对象上修改
  1. 通过 del df[“列名”] 删除
del df["phone"]

插入列:通过 insert(loc, column, value) 插入。该方法没有inplace参数,直接在原数据上修改。

# loc 参数需要一个整数,代表列的索引位置。loc=0 表示将新列插入到 DataFrame 的最前面,成为第一列。
# 新列的名称是 "phone"
# 将 "age" 列中的每一个值与它对应的行索引值进行逐元素相乘,就是新列 "phone" 中要填充的数据
df.insert(loc=0, column="phone", value=df["age"] * df.index)

2.2.4、DataFrame的数据导入与导出

  1. 导出数据
方法 说明
to_csv() 将数据保存为csv格式文件,数据之间以逗号分隔,可通过sep参数设置使用其他分隔符,可通过index参数设置是否保存行标签,可通过header参数设置是否保存列标签。
to_pickle() 如要保存的对象是计算的中间结果,或者保存的对象以后会在Python中复用,可把对象保存为.pickle文件。如果保存成pickle文件,只能在python中使用。文件的扩展名可以是.p、.pkl、.pickle。
to_excel() 保存为Excel文件,需安装openpyxl包。
to_clipboard() 保存到剪切板。
to_dict() 保存为字典。
to_hdf() 保存为HDF格式,需安装tables包。
to_html() 保存为HTML格式,需安装lxml、html5lib、beautifulsoup4包。
to_json() 保存为JSON格式。
to_feather() feather是一种文件格式,用于存储二进制对象。feather对象也可以加载到R语言中使用。feather格式的主要优点是在Python和R语言之间的读写速度要比csv文件快。feather数据格式通常只用中间数据格式,用于Python和R之间传递数据,一般不用做保存最终数据。需安装pyarrow包。
to_sql() 保存到数据库。
import os
import pandas as pd

os.makedirs("data", exist_ok=True)
df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True)

df.to_csv("data/df.csv")
df.to_csv("data/df.tsv", sep="\t") # 设置分隔符为 \t
df.to_csv("data/df_noindex.csv", index=False) # index=False 不保存行索引
df.to_pickle("data/df.pkl")
df.to_excel("data/df.xlsx")
df.to_clipboard()
df_dict = df.to_dict()
df.to_hdf("data/df.h5", key="df")
df.to_html("data/df.html")
df.to_json("data/df.json")
df.to_feather("data/df.feather")
  1. 导入数据
方法 说明
read_csv() 加载csv格式的数据。可通过sep参数指定分隔符,可通过index_col参数指定行索引。
read_pickle() 加载pickle格式的数据。
read_excel() 加载Excel格式的数据。
read_clipboard() 加载剪切板中的数据。
read_hdf() 加载HDF格式的数据。
read_html() 加载HTML格式的数据。
read_json() 加载JSON格式的数据。
read_feather() 加载feather格式的数据。
read_sql() 加载数据库中的数据。
df_csv = pd.read_csv("data/df.csv", index_col="id")  # 指定行索引
df_tsv = pd.read_csv("data/df.tsv", sep="\t")  # 指定分隔符
df_pkl = pd.read_pickle("data/df.pkl")
df_excel = pd.read_excel("data/df.xlsx", index_col="id")
df_clipboard = pd.read_clipboard(index_col="id")
df_from_dict = pd.DataFrame(df_dict)
df_hdf = pd.read_hdf("data/df.h5", key="df")
df_html = pd.read_html("data/df.html", index_col=0)[0]
df_json = pd.read_json("data/df.json")
df_feather = pd.read_feather("data/df.feather")

print(df_csv)
print(df_tsv)
print(df_pkl)
print(df_excel)
print(df_clipboard)
print(df_from_dict)
print(df_hdf)
print(df_html)
print(df_json)
print(df_feather)

2.3、MultiIndex

MultiIndex是三维的数据结构;多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。

2.3.1、创建MultiIndex

  • MultiIndex.from_arrays():传入一个数组列表
arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))

在这里插入图片描述

忙忒Index

2.3.2、MultiIndex的属性

  • index属性
    • names:levels的名称
    • levels:每个level的元组值

待补充

2.4、排序

排序有两种形式,一种对于索引进行排序,一种对于内容进行排序

2.4.1、DataFrame排序

使用df.sort_values(by=, ascending=)单个键或者多个键进行排序

  • by:指定排序参考的键
  • ascending:默认升序
    • ascending=False:降序
    • ascending=True:升序
# 按照开盘价大小进行排序 , 使用ascending指定按照大小排序
data.sort_values(by="open", ascending=True).head()

# 按照多个键进行排序
data.sort_values(by=['open', 'high'])

在这里插入图片描述

  • 使用df.sort_index给索引进行排序

这个股票的日期索引原来是从大到小,现在重新排序,从小到大

# 对索引进行排序
data.sort_index()

在这里插入图片描述

2.4.2、Series排序

  • 使用series.sort_values(ascending=True)进行排序

series排序时,只有一列,不需要参数

data['p_change'].sort_values(ascending=True).head()

在这里插入图片描述

  • 使用series.sort_index()对索引进行排序

3、Pandas日期数据处理

3.1、to_datetime()进行日期格式转换

参数说明:

参数名 说明
arg 要转换为日期时间的对象
errors ignore,raise,coerce, 默认为ignore,表示无效的解析将会返回原值
dayfirst 指定日期解析顺序。如果为True,则以日期开头解析日期,例如:“10/11/12”解析为2012-11-10。默认false
yearfirst 如果为True,则以日期开头解析,例如:“10/11/12”解析为2010-11-12。如果dayfirst和yearfirst都为True,则yearfirst在前面。默认false。当日期字符串格式不明确时,指定年份是否在最前面。当日期字符串是 ‘2010/1/4’ 这种形式,由于年份是 4 位数字,pandas 能很清晰地识别出这是年份,所以即使 yearfirst 为 False,也不会影响其正确解析
utc 返回utc,即协调世界时间
format 格式化显示时间的格式,字符串,默认值为None
exact 要求格式完全匹配
unit 参数的单位表示时间的单位
infer_datetime_format 如果为True且未给出格式,则尝试基于第一个非nan元素推断datetime字符串的格式,如果可以推断,则切换到更快的解析方法。在某些情况下,这可以将解析速度提高5-10倍。
origin 默认值为unix,定义参考日期1970-01-01
cache 使用唯一的已转换日期缓存来应用日期时间转换。在解析重复日期字符串时产生显著的加速。
  1. 将字符串字段转换为日期类型
import pandas as pd
df = pd.DataFrame({"gmv":[100,200,300,400],"trade_date":["2025-01-06","2023-10-31","2023-12-31","2023-01-05"]})
# 原本 trade_date 列中的日期只是普通的文本(字符串),计算机无法理解其时间先后顺序。转换后,ymd 列变成了真正的时间格式,可以进行时间计算、排序或提取年份/月份等操作
df["ymd"] = pd.to_datetime(df["trade_date"])
print(df)

在这里插入图片描述

3.2、获取年月日星期

  1. 获取年月日
import pandas as pd
df = pd.DataFrame({"gmv":[100,200,300,400],"trade_date":["2025-01-06","2023-10-31","2023-12-31","2023-01-05"]})
# 原本 trade_date 列中的日期只是普通的文本(字符串),计算机无法理解其时间先后顺序。转换后,ymd 列变成了真正的时间格式,可以进行时间计算、排序或提取年份/月份等操作
df["ymd"] = pd.to_datetime(df["trade_date"])


# 1. 提取年份:从 ymd 列中取出年份(如 2025),存入新列 'yy'
df['yy'] = df['ymd'].dt.year

# 2. 提取月份:从 ymd 列中取出月份(如 1),存入新列 'mm'
df['mm'] = df['ymd'].dt.month

# 3. 提取日期:从 ymd 列中取出日期(如 6),存入新列 'dd'
df['dd'] = df['ymd'].dt.day
print(df)

在这里插入图片描述

  1. 获取星期
df['week']=df['ymd'].dt.day_name()
print(df)
  1. 获取日期所在季度
df['quarter']=df['ymd'].dt.quarter
print(df)
  1. 判断日期是否月底年底
df['mend']=df['ymd'].dt.is_month_end
df['yend']=df['ymd'].dt.is_year_end
print(df)

3.3、to_period()获取统计周期

freq:这是 to_period() 方法最重要的参数,用于指定要转换的时间周期频率

常见的取值如下:

  • D:按天周期,例如 2024-01-01 会转换为 2024-01-01 这个天的周期
  • W:按周周期,通常以周日作为一周的结束,比如日期落在某一周内,就会转换为该周的周期表示。
  • M:按月周期,像 2024-05-15 会转换为 2024-05
  • Q:按季度周期,一年分为四个季度,日期会转换到对应的季度周期,例如 2024Q2
  • A或Y:按年周期,如 2024-07-20 会转换为 2024
import pandas as pd
df = pd.DataFrame({"gmv":[100,200,300,400],"trade_date":["2025-01-06","2023-10-31","2023-12-31","2023-01-05"]})
# 原本 trade_date 列中的日期只是普通的文本(字符串),计算机无法理解其时间先后顺序。转换后,ymd 列变成了真正的时间格式,可以进行时间计算、排序或提取年份/月份等操作
df["ymd"] = pd.to_datetime(df["trade_date"])

df["ystat"] = df["ymd"].dt.to_period("Y")
df["mstat"] = df["ymd"].dt.to_period("M")
df["qstat"] = df["ymd"].dt.to_period("Q")
df["wstat"] = df["ymd"].dt.to_period("W")
print(df)

在这里插入图片描述

4、Pandas画图

使用pandas.DataFrame的plot方法绘制图像会按照数据的每一列绘制一条曲线,默认按照列columns的名称在适当的位置展示图例,比matplotlib绘制节省时间,且DataFrame格式的数据更规范,方便向量化及计算。

4.1、折线图Line

  1. 普通用法
ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
ts = ts.cumsum().plot()
  • np.random.randn(1000): 这部分是利用NumPy库生成一个包含1000个元素的数组,这些元素是从标准正态分布(均值为0,标准差为1的正态分布)中随机抽取的。
  • pd.Series(...): 这部分是将上述生成的随机数组转换为一个Pandas的Series对象。Pandas的Series是一种一维数组结构,它可以存储任何数据类型(整数、字符串、浮点数、Python对象等),每个元素都有一个标签(索引)。
  • index=pd.date_range("1/1/2000", periods=1000): 这里为Series对象指定了一个索引。pd.date_range函数生成了一个日期范围,从"1/1/2000"(即2000年1月1日)开始,总共生成1000个日期。这意味着每个随机生成的数值都会与一个特定的日期相关联。

在这里插入图片描述

  1. 展示多列数据
df = pd.DataFrame(np.random.randn(1000, 4), index=pd.date_range("1/1/2000", periods=1000), columns=list("ABCD"))
df = df.cumsum().plot()
  • np.random.randn(1000, 4): 这部分生成了一个1000行4列的数组,数组中的每个元素都是从标准正态分布中随机抽取的。这意味着你将有1000个观测值,每个观测值都有4个特征或变量。
  • pd.DataFrame(...): 这部分将上述生成的随机数组转换为一个Pandas的DataFrame对象。DataFrame是Pandas中用于存储和操作结构化数据的主要数据结构。
  • index=pd.date_range("1/1/2000", periods=1000): 与之前的示例类似,这里为DataFrame指定了一个索引。pd.date_range函数生成了一个从"1/1/2000"(即2000年1月1日)开始的日期范围,总共1000个日期。这些日期将作为DataFrame的行索引。
  • columns=list("ABCD"): 这里为DataFrame指定了列标签。list("ABCD")创建了一个包含四个字符串(“A”, “B”, “C”, “D”)的列表,这些字符串将作为DataFrame的列名。

在这里插入图片描述

在这里插入图片描述

若要让时间刻度良好展示,可以:

plot(x_compat=True)

在这里插入图片描述

4.2、条形图bar

df = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
df.plot.bar()

在这里插入图片描述

若要生成堆积条形图,可加参数

bar(stacked=True)

在这里插入图片描述

若要生成水平条形图:

df.plot.barh()

在这里插入图片描述

剩余图形请参考更好的文章:pandas plot绘图详解:一文教会你各种绘图

5、Pandas数据组合函数

5.1、Concat连接

沿着一条轴将多个对象堆叠到一起,可通过axis参数设置沿哪一条轴连接。

  1. Series与Series连接
import pandas as pd

s1 = pd.Series(["A", "B"], index=[1, 2])
s2 = pd.Series(["D", "E"], index=[4, 5])
s3 = pd.Series(["G", "H"], index=[7, 8])

s4 = pd.concat([s1, s2, s3]) # 按行连接
print(s4)
"""
1    A
2    B
4    D
5    E
7    G
8    H
dtype: object
"""

在这里插入图片描述

s5 = pd.concat([s1, s2, s3], axis=1) # 按列连接 ,缺失值会用NaN填充
print(s5)
"""
     0    1    2
1    A  NaN  NaN
2    B  NaN  NaN
4  NaN    D  NaN
5  NaN    E  NaN
7  NaN  NaN    G
8  NaN  NaN    H
"""

在这里插入图片描述

  1. DataFrame与Series连接
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
s1 = pd.Series(data=[7, 10], index=[1, 2], name="a")

pd.concat([df1, s1])  # 按行连接
#     a    b
# 1   1  4.0
# 2   2  5.0
# 1   7  NaN
# 2  10  NaN

pd.concat([df1, s1], axis=1)  # 按列连接
#    a  b   a
# 1  1  4   7
# 2  2  5  10

在这里插入图片描述

  1. DataFrame与DataFrame连接
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
df2 = pd.DataFrame(data={"a": [7, 8], "b": [10, 11]}, index=[1, 2])

pd.concat([df1, df2])  # 按行连接
#    a   b
# 1  1   4
# 2  2   5
# 1  7  10
# 2  8  11

pd.concat([df1, df2], axis=1)  # 按列连接
#    a  b  a   b
# 1  1  4  7  10
# 2  2  5  8  11

在这里插入图片描述

  1. 可通过ignore_index=True来重置索引
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
df2 = pd.DataFrame(data={"a": [7, 8], "b": [10, 11]}, index=[1, 2])

pd.concat([df1, df2], ignore_index=True)  # 重置索引
#    a   b
# 0  1   4
# 1  2   5
# 2  7  10
# 3  8  11
  1. join:默认的合并方式是对其他轴进行并集合并(join=outer),可以用join=inner实现其他轴上的交集合并。
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
df2 = pd.DataFrame(data={"b": [7, 8], "c": [10, 11]}, index=[2, 3])

pd.concat([df1, df2])
#      a  b     c
# 1  1.0  4   NaN
# 2  2.0  5   NaN
# 2  NaN  7  10.0
# 3  NaN  8  11.0

pd.concat([df1, df2], join="inner")
#    b
# 1  4
# 2  5
# 2  7
# 3  8

5.2、merge

merge合并:通过一个或多个列将行连接

merge()实现了三种数据连接的类型:一对一、多对一和多对多:

(1)、一对一连接

df1 = pd.DataFrame(
    {"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"employee": ["Lisa", "Bob", "Jake", "Sue"], "hire_date": [2004, 2008, 2012, 2014]})
print(df1)
#   employee        group
# 0      Bob   Accounting
# 1     Jake  Engineering
# 2     Lisa  Engineering
# 3      Sue           HR
print(df2)
#   employee  hire_date
# 0     Lisa       2004
# 1      Bob       2008
# 2     Jake       2012
# 3      Sue       2014


# 通过相同的字段名employee进行关联的
df3 = pd.merge(df1, df2)
print(df3)
#   employee        group  hire_date
# 0      Bob   Accounting       2008
# 1     Jake  Engineering       2012
# 2     Lisa  Engineering       2004
# 3      Sue           HR       2014

(2)、多对一连接:在需要连接的两个列中,有一列的值有重复。通过多对一连接获得的结果将会保留重复值。

df1 = pd.DataFrame(
    {"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"group": ["Accounting", "Engineering", "HR"], "supervisor": ["Carly", "Guido", "Steve"]})
print(df1)
#   employee        group
# 0      Bob   Accounting
# 1     Jake  Engineering
# 2     Lisa  Engineering
# 3      Sue           HR

print(df2)
#          group supervisor
# 0   Accounting      Carly
# 1  Engineering      Guido
# 2           HR      Steve

# 通过相同的字段名group进行关联的
df3 = pd.merge(df1, df2)
print(df3)
#   employee        group supervisor
# 0      Bob   Accounting      Carly
# 1     Jake  Engineering      Guido
# 2     Lisa  Engineering      Guido
# 3      Sue           HR      Steve

在supervisor列中有些值会因为输入数据的对应关系而有所重复。

(3)、多对多连接:如果左右两个输入的共同列都包含重复值,那么合并的结果就是一种多对多连接

df1 = pd.DataFrame(
    {"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame(
    {
        "group": ["Accounting", "Accounting", "Engineering", "Engineering", "HR", "HR"],
        "skills": ["math", "spreadsheets", "coding", "linux", "spreadsheets", "organization"],
    }
)
print(df1)
#   employee        group
# 0      Bob   Accounting
# 1     Jake  Engineering
# 2     Lisa  Engineering
# 3      Sue           HR

print(df2)
#          group        skills
# 0   Accounting          math
# 1   Accounting  spreadsheets
# 2  Engineering        coding
# 3  Engineering         linux
# 4           HR  spreadsheets
# 5           HR  organization


df3 = pd.merge(df1, df2)
print(df3)
#   employee        group        skills
# 0      Bob   Accounting          math
# 1      Bob   Accounting  spreadsheets
# 2     Jake  Engineering        coding
# 3     Jake  Engineering         linux
# 4     Lisa  Engineering        coding
# 5     Lisa  Engineering         linux
# 6      Sue           HR  spreadsheets
# 7      Sue           HR  organization

多对多连接产生的是行的笛卡尔积。由于左边有2个Engineering,右边有2个Engineering,所以最终结果有4个Engineering。

(4)、设置合并的键与索引:merge()会将两个输入的一个或多个共同列作为键进行合并。但由于两个输入要合并的列通常都不是同名的,因此merge()提供了一些参数处理这个问题。

  1. 通过on指定使用某个列连接,只能在有共同列名的时候使用
df1 = pd.DataFrame(
    {"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"employee": ["Lisa", "Bob", "Jake", "Sue"], "hire_date": [2004, 2008, 2012, 2014]})
print(df1)
#   employee        group
# 0      Bob   Accounting
# 1     Jake  Engineering
# 2     Lisa  Engineering
# 3      Sue           HR

print(df2)
#   employee  hire_date
# 0     Lisa       2004
# 1      Bob       2008
# 2     Jake       2012
# 3      Sue       2014

# 指定使用 employee 列进行连接
df3 = pd.merge(df1, df2, on="employee")
print(df3)
#   employee        group  hire_date
# 0      Bob   Accounting       2008
# 1     Jake  Engineering       2012
# 2     Lisa  Engineering       2004
# 3      Sue           HR       2014
  1. 两对象列名不同,通过left_on和right_on分别指定列名
df1 = pd.DataFrame(
    {"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"name": ["Bob", "Jake", "Lisa", "Sue"], "salary": [70000, 80000, 120000, 90000]})
print(df1)
#   employee        group
# 0      Bob   Accounting
# 1     Jake  Engineering
# 2     Lisa  Engineering
# 3      Sue           HR

print(df2)
#    name  salary
# 0   Bob   70000
# 1  Jake   80000
# 2  Lisa  120000
# 3   Sue   90000

# 将 df1 和 df2 按照 df1 的 "employee" 列与 df2 的 "name" 列进行匹配,把匹配成功的行合并成一个新的 DataFrame df3
df3 = pd.merge(df1, df2, left_on="employee", right_on="name")
print(df3)
#   employee        group  name  salary
# 0      Bob   Accounting   Bob   70000
# 1     Jake  Engineering  Jake   80000
# 2     Lisa  Engineering  Lisa  120000
# 3      Sue           HR   Sue   90000
  1. 通过left_index和right_index设置合并的索引:通过设置merge()中的left_index、right_index参数将索引设置为键来实现合并。
df1 = pd.DataFrame(
    {"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"employee": ["Lisa", "Bob", "Jake", "Sue"], "hire_date": [2004, 2008, 2012, 2014]})
df1.set_index("employee", inplace=True)
df2.set_index("employee", inplace=True)

print(df1)
#                 group
# employee
# Bob        Accounting
# Jake      Engineering
# Lisa      Engineering
# Sue                HR

print(df2)
#           hire_date
# employee
# Lisa           2004
# Bob            2008
# Jake           2012
# Sue            2014

# 设置索引后,如果不指定关联列会报错,建议通过以下方式指定,on="employee"也可#以实现,但是不同的解释器可能效果不一样,因为设置索引后,employee就不算是列了
df3 = pd.merge(df1, df2, left_index=True, right_index=True)
#                 group  hire_date
# employee
# Bob        Accounting       2008
# Jake      Engineering       2012
# Lisa      Engineering       2004
# Sue                HR       2014

DataFrame实现了join()方法,可以按照索引进行数据合并。但要求没有重叠的列,或通过lsuffix、rsuffix指定重叠列的后缀。

import pandas as pd

df1 = pd.DataFrame({
    'key': ['A', 'B', 'C'],
    'value1': [1, 2, 3]
})

df2 = pd.DataFrame({
    'key': ['B', 'C', 'D'],
    'value2': [4, 5, 6]
})

# 合并两个 DataFrame,并处理列名冲突
df1.join(df2,lsuffix='_left',rsuffix='_right')

(5)、设置数据连接的集合操作规则:当一个值出现在一列,却没有出现在另一列时,就需要考虑集合操作规则了。

df1 = pd.DataFrame({"name": ["Peter", "Paul", "Mary"], "food": ["fish", "beans", "bread"]}, columns=["name", "food"])
df2 = pd.DataFrame({"name": ["Mary", "Joseph"], "drink": ["wine", "beer"]}, columns=["name", "drink"])
print(df1)
#     name   food
# 0  Peter   fish
# 1   Paul  beans
# 2   Mary  bread

print(df2)
#      name drink
# 0    Mary  wine
# 1  Joseph  beer

print(pd.merge(df1, df2))
#    name   food drink
# 0  Mary  bread  wine

6、Pandas的缺失值处理函数

pandas使用浮点值NaN(Not a Number)表示缺失数据,使用NA(Not Available)表示缺失值。可以通过isnull()、isna()或notnull()、notna()方法判断某个值是否为缺失值。

  • na和nan都用于表示缺失值,但nan更强调是数值计算中的特殊值,而na更强调数据的可用性或存在性。
import pandas as pd
import numpy as np

s = pd.Series([np.nan, None, pd.NA])
print(s)

"""
0     NaN
1    None
2    <NA>
dtype: object
"""

print(s.isnull())
"""
0    True
1    True
2    True
dtype: bool
"""

6.1、剔除缺失值

  1. Series剔除缺失值
s = pd.Series([1, pd.NA, None])
print(s)
# 0       1
# 1    <NA>
# 2    None
# dtype: object

print(s.dropna())
# 0    1
# dtype: object
  1. DataFrame剔除缺失值:无法从DataFrame中单独剔除一个值,只能剔除缺失值所在的整行或整列。默认情况下,dropna()会剔除任何包含缺失值的整行数据。
df = pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])
print(df)
#       0     1  2
# 0     1  <NA>  2
# 1     2     3  5
# 2  <NA>     4  6
print(df.dropna())
#    0  1  2
# 1  2  3  5

可以设置按不同的坐标轴剔除缺失值,比如axis=1(或 axis=‘columns’)会剔除任何包含缺失值的整列数据。

df = pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])
print(df)
#       0     1  2
# 0     1  <NA>  2
# 1     2     3  5
# 2  <NA>     4  6
print(df.dropna(axis=1))
#    2
# 0  2
# 1  5
# 2  6

有时只需要剔除全部是缺失值的行或列,或者绝大多数是缺失值的行或列。这些需求可以通过设置how或thresh参数来满足,它们可以设置剔除行或列缺失值的数量阈值。

df = pd.DataFrame([[1, pd.NA, 2], [pd.NA, pd.NA, 5], [pd.NA, pd.NA, pd.NA]])
print(df)
#       0     1     2
# 0     1  <NA>     2
# 1  <NA>  <NA>     5
# 2  <NA>  <NA>  <NA>
print(df.dropna(how="all"))  # 如果所有值都是缺失值,则删除这一行
#       0     1  2
# 0     1  <NA>  2
# 1  <NA>  <NA>  5
print(df.dropna(thresh=2))  # 如果至少有2个值不是缺失值,则保留这一行
#    0     1  2
# 0  1  <NA>  2

可以通过设置subset参数来设置某一列有缺失值则进行剔除。

df = pd.DataFrame([[1, pd.NA, 2], [pd.NA, pd.NA, 5], [pd.NA, pd.NA, pd.NA]])
print(df)
#       0     1     2
# 0     1  <NA>     2
# 1  <NA>  <NA>     5
# 2  <NA>  <NA>  <NA>
print(df.dropna(subset=[0]))  # 如果0列有缺失值,则删除这一行
#    0     1  2
# 0  1  <NA>  2

6.2、填充缺失值

  1. 用固定值填充所有缺失值
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, 7, 8]
})

# 用 0 填充所有 NaN
df_filled = df.fillna(0)
print(df_filled)

在这里插入图片描述

  1. 为不同列设置不同的填充值
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, 7, 8]
})

# 用字典指定每列的填充值(A列填充0,B列填充100)
df_filled = df.fillna({'A': 0, 'B': 100})
print(df_filled)

在这里插入图片描述

  1. 前向填充(Forward Fill)——用前一个有效值填充
df_filled = df.fillna(method='ffill')
print(df_filled)
"""
A    B
0  1.0  5.0
1  2.0  5.0
2  2.0  7.0
3  4.0  8.0
"""
  1. 后向填充(Backward Fill)——用后一个有效值填充
df_filled = df.fillna(method='bfill')
print(df_filled)
"""
A    B
0  1.0  5.0
1  2.0  7.0
2  4.0  7.0
3  4.0  8.0
"""
  1. 用列的均值/中位数/众数填充
# 用每列的均值填充
df_filled = df.fillna(df.mean())
print(df_filled)

在填充前,通常先查看哪些地方有缺失:

# 查看每列缺失值数量
print(df.isnull().sum())

# 查看整个 DataFrame 的缺失情况
print(df.isnull())

7、文件读取与存储

我们的数据大部分存在于文件当中,所以pandas会支持复杂的IO操作,pandas的API支持众多的文件格式,如CSV、SQL、XLS、JSON、HDF5。

注:最常用的HDF5和CSV文件

  • pandas.read_csv(filepath_or_buffer, sep =',', usecols )
    • filepath_or_buffer:文件路径
    • sep :分隔符,默认用","隔开
    • usecols:指定读取的列名,列表形式
# 读取文件,并且指定只获取'open', 'close'指标
data = pd.read_csv("./KuangStudy_Data/01_stock_day.csv", usecols=['open', 'close'])

在这里插入图片描述

  • DataFrame.to_csv(path_or_buf=None, sep=', ’, columns=None, header=True, index=True, mode='w', encoding=None):保存文件

    • path_or_buf :文件路径
    • sep :分隔符,默认用","隔开
    • columns :选择需要的列索引
    • header :boolean or list of string, default True,是否写进列索引值
    • index:是否写进行索引
    • mode:‘w’:重写, ‘a’ 追加
  • 举例:保存读取出来的股票数据

    • 保存’open’列的数据,然后读取查看结果
# 选取10行数据保存,便于观察数据
data[:10].to_csv("./KuangStudy_Data/02_stock_save.csv", columns=['open'])

在这里插入图片描述

会发现将索引(也就是时间)存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。

# index:存储不会将索引值变成一列数据
data[:10].to_csv("./KuangStudy_Data/02_stock_save.csv", columns=['open'], index=False)

在这里插入图片描述

7.1、HDF5

7.1.1、read_hdf与to_hdf

HDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame

  • pandas.read_hdf(path_or_buf,key =None,** kwargs):从h5文件当中读取数据
    • path_or_buffer:文件路径
    • key:读取的键
    • return:Theselected object
  • DataFrame.to_hdf(path_or_buf, key, ** kwargs)
# 读取文件
day_close = pd.read_hdf("./KuangStudy_Data/02_day_close.h5")

在这里插入图片描述

  • 存储文件
# 存储的时候需要给个key
day_close.to_hdf("./KuangStudy_Data/02_day_close_save.h5", key="day_close")

再次读取的时候, 需要指定键的名字

new_close = pd.read_hdf("./data/test.h5", key="day_close")

注意:优先选择使用HDF5文件存储

  • HDF5在存储的时候支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的
  • 使用压缩可以提磁盘利用率,节省空间
  • HDF5还是跨平台的,可以轻松迁移到hadoop 上面

7.2、JSON

  • pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False):将JSON格式准换成默认的Pandas DataFrame格式
    • path_or_buf: json文件的路径
    • orient
      • split:index -> [index], columns -> [columns], data -> [values]。split 将索引总结到索引,列名到列名,数据到数据。将三部分都分开了
      • records:records 以columns:values的形式输出
      • index:ndex 以index:{columns:values}...的形式输出
      • columns:colums 以columns:{index:values}的形式输出
      • values:values 直接输出值
    • typ : default ‘frame’, 指定转换成的对象类型series或者dataframe
    • lines : boolean, default False。按照每行读取json对象
# orient指定存储的json格式,lines指定按照行去变成一个样本
json_read = pd.read_json("./KuangStudy_Data/03_Dataset.json", orient="records", lines=True)

其中03_Dataset.json里面的数据如下:

在这里插入图片描述

在这里插入图片描述

  • DataFrame.to_json(path_or_buf=None, orient=None, lines=False) : 将Pandas 对象存储为json格式
    • path_or_buf=None:文件地址
    • orient:存储的json形式,{‘split’,’records’,’index’,’columns’,’values’}
    • lines:一个对象存储为一行
# 存储文件
json_read.to_json("./KuangStudy_Data/03_Dataset_save.json", orient='records')

更多推荐