Pandas 概述

NumPy 能够帮助我们处理数值,但 Pandas 除了处理数值之外(基于 NumPy),还能够帮助我们处理其他类型的数据。

Series

Series 的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import string

# 方法一:通过数组创建
t = pd.Series(np.arange(10), index=list(string.ascii_uppercase[:10]))

# 方法二:通过字典创建
a = {string.ascii_uppercase[i]: i for i in range(10)}
pd.Series(a)
# out:
# A 0
# B 1
# ...
# J 9
# dtype: int64

# 重新指定索引
pd.Series(a, index=list(string.ascii_uppercase[5:15]))
# out:
# F 5.0
# G 6.0
# ...
# O NaN
# dtype: float64

重新指定索引后,如果能够对应上就取其值,不能则为 NaN。类型变为 float 是因为 NumPy 中 nan 为 float,Pandas 会自动根据数据更改 Series 的 dtype 类型。

Series 切片和索引

切片:直接传入 start、end 或步长即可。

索引:一个的时候直接传入序号或 index,多个的时候传入序号或 index 的列表。

1
2
3
4
5
6
7
8
t = pd.Series(np.arange(10), index=list("ABCDEFGHIJ"))

t[2:10:2] # 切片,步长为2
t[1] # 取索引
t[[2, 3, 6]] # 取多个索引
t[t > 4] # 值大于4的所有数据
t["F"] # 索引为F的数据
t[["A", "F", "g"]] # 索引为A、F、g的数据,g不存在则为NaN

Series 的索引和值

Series 对象本质上由两个数组构成:一个构成对象的键(index),一个构成对象的值(values)。

1
2
3
4
5
t.index    # Index(['A', 'B', ...], dtype='object')
t.values # array([0, 1, 2, ...])

type(t.index) # pandas.core.indexes.base.Index
type(t.values) # numpy.ndarray

ndarray 的很多方法都可以运用于 Series 类型,比如 argmax、clip。

tolist() 和 unique()

1
2
3
4
df = pd.Series([1, 2, 1, 3, 2, 1])

df.tolist() # [1, 2, 1, 3, 2, 1]
df.unique() # array([1, 2, 3])

读取外部数据

1
2
pd.read_csv(filepath)
pd.read_sql(sql_sentence, connection)

DataFrame

DataFrame 的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 方法一:通过二维数组创建
t = pd.DataFrame(np.arange(12).reshape(3, 4),
index=list("ABC"),
columns=list("WXYZ"))

# 方法二:通过字典创建(值为列表)
t_dict = {
"name": ["zhangsan", "lisi"],
"age": [12, 20],
}
pd.DataFrame(t_dict)

# 方法三:通过字典列表创建
t_dict = [
{"name": "zhangsan", "age": 12},
{"name": "lisi", "age": 20},
]
pd.DataFrame(t_dict)

DataFrame 的基础属性和整体情况查询

1
2
3
4
5
6
7
8
9
10
11
12
13
# 基础属性
df.shape # 行数、列数
df.dtypes # 列数据类型
df.ndim # 数据维度
df.index # 行索引
df.columns # 列索引
df.values # 对象值,二维 ndarray 数组

# 整体情况查询
df.head(3) # 显示头部几行,默认5行
df.tail(3) # 显示尾部几行,默认5行
df.info() # 相关信息概览:行数、列数、列索引、列非空值个数、列类型、内存占用
df.describe() # 快速综合统计结果:计数、均值、标准差、最大值、四分位数、最小值

对某一列进行排序

1
2
# ascending=False 表示从大到小排序
df.sort_values(by="Count_AnimalName", ascending=False)

DataFrame 取行或列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df = pd.DataFrame(np.arange(56).reshape(7, 8),
index=list("ABCDEFG"),
columns=list("STUVWXYZ"))

# 取第X列
df["X"]

# 取第X、Z列
df[["X", "Z"]]

# 取第3到第6行
df[2:6]

# 取第3到第6行和第X列
df[2:6]["X"]

loc 和 iloc

  • df.loc:通过标签索引行数据
  • df.iloc:通过位置获取行数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# loc:取A行、W列交集的数据
df.loc["A", "W"]

# loc:取A行和W、Z交集的数据
df.loc["A", ["W", "Z"]]

# loc:取A、C行和W、Z交集的数据
df.loc[["A", "C"], ["W", "Z"]]

# loc:取A行到C行和W、Z的交集
df.loc["A":"C", ["W", "Z"]]

# iloc:取第2行到第3行和第3列、第4列的交集
df.iloc[1:3, [2, 3]]

# iloc:取第2行到第3行和第2列到第3列的交集
df.iloc[1:3, 1:3]

赋值更改数据:

1
2
df.loc["A", "Y"] = 100
df.iloc[1:2, 0:2] = 200

DataFrame 布尔索引

1
2
3
4
5
6
7
# 找到使用次数超过800的狗的名字
df[df["Count_AnimalName"] > 800]

# 找到所有使用次数超过700并且名字长度大于4的狗的名字
df[(df["Row_Labels"].str.len() > 4) & (df["Count_AnimalName"] > 700)]

# & 表示且,| 表示或

缺失数据的处理

1
2
3
4
5
6
7
8
9
10
11
# 判断数据是否为NaN
pd.isnull(df) # 是NaN
pd.notnull(df) # 不是NaN

# 删除NaN所在的行列
df.dropna(axis=0, how='any', inplace=False)

# 填充数据
t.fillna(t.mean()) # 用均值填充
t.fillna(t.median()) # 用中值填充
t.fillna(0) # 用0填充

处理为0的数据:t[t == 0] = np.nan

注意:并不是每次为0的数据都需要处理。计算平均值等情况,nan 不参与计算,但0会。

常用统计方法

1
2
3
4
5
6
7
8
9
10
11
12
13
# 评分的平均分
rating_mean = df["Rating"].mean()

# 导演的人数
temp_list = df["Actors"].str.split(",").tolist()
nums = set([i for j in temp_list for i in j])

# 电影时长的最大最小值
max_runtime = df["Runtime(Minutes)"].max()
max_runtime_index = df["Runtime(Minutes)"].argmax()
min_runtime = df["Runtime(Minutes)"].min()
min_runtime_index = df["Runtime(Minutes)"].argmin()
runtime_median = df["Runtime(Minutes)"].median()

数据合并

join

默认情况下把行索引相同的数据合并到一起。

1
t1.join(t2)

merge

按照指定的列把数据按照一定的方式合并到一起。

1
t1.merge(t2, left_on="O", right_on="X")

合并方式(how 参数):

方式 说明
inner 内连接(默认),取交集
outer 外连接,取并集,NaN 补全
left 左连接,以左边为准,NaN 补全
right 右连接,以右边为准,NaN 补全

分组和聚合

1
grouped = df.groupby(by="columns_name")

grouped 是一个 DataFrameGroupBy 对象,是可迭代的。grouped 中的每一个元素是一个元组,元组里面是(索引(分组的值),分组之后的 DataFrame)。

对多列进行分组:

1
grouped = df.groupby(by=[df["Country"], df["State/Province"]])

获取分组之后的某一部分数据:

1
df.groupby(by=["Country", "State/Province"])["Country"].count()

对某几列数据进行分组:

1
df["Country"].groupby(by=[df["Country"], df["State/Province"]]).count()

返回 DataFrame 类型:

1
2
t1 = df[["Country"]].groupby(by=[df["Country"], df["State/Province"]]).count()
t2 = df.groupby(by=["Country", "State/Province"])[["Country"]].count()

索引和复合索引

简单的索引操作:

1
2
3
4
5
df.index                            # 获取 index
df.index = ['x', 'y'] # 指定 index
df.reindex(list("abcedf")) # 重新设置 index
df.set_index("Country", drop=False) # 指定某一列作为 index
df.set_index("Country").index.unique() # 返回 index 的唯一值

复合索引:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = pd.DataFrame({
'a': range(7),
'b': range(7, 0, -1),
'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
'd': list("hjklmno")
})

x = a.set_index(["c", "d"])["a"]
# out:
# c d
# one h 0
# j 1
# k 2
# two l 3
# m 4
# n 5
# o 6

x["one", "h"] # out: 0

交换复合索引:

1
2
3
4
5
6
x = x.swaplevel()
# out:
# d c
# h one 0
# j one 1
# ...

时间序列

时间序列的生成

1
pd.date_range(start=None, end=None, periods=None, freq='D')
  • startend 以及 freq 配合能够生成范围内以频率 freq 的一组时间索引
  • startperiods 以及 freq 配合能够生成从 start 开始的频率为 freqperiods 个时间索引

频率缩写:

别名 说明
D 每日历日
B 每工作日
H 每小时
T 或 MIN 每分
S 每秒
L 或 MS 每毫秒
U 每微秒
M 每月最后一个日历日
BM 每月最后一个工作日
MS 每月第一个日历日
BMS 每月第一个工作日

在 DataFrame 中使用时间序列

1
2
index = pd.date_range("20170101", periods=10)
df = pd.DataFrame(np.random.rand(10), index=index)

把时间字符串转化为时间序列:

1
df["timeStamp"] = pd.to_datetime(df["timeStamp"], format="")

format 参数大部分情况下可以不用写,但对于 Pandas 无法格式化的时间字符串(比如包含中文),可以使用该参数。

重采样

重采样:将时间序列从一个频率转化为另一个频率进行处理。将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样。

1
2
3
4
5
6
7
8
# 降采样:按月求均值
t.resample("M").mean()

# 降采样:按10天计数
t.resample("10D").count()

# 按季度计数
t.resample("QS-JAN").count()

PeriodIndex

DatetimeIndex 可以理解为时间戳,PeriodIndex 可以理解为时间段。

1
2
3
4
5
6
7
periods = pd.PeriodIndex(
year=data["year"],
month=data["month"],
day=data["day"],
hour=data["hour"],
freq="H"
)

本站由 sswfive 使用 Stellar 1.42.0 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站总访问量