pandas
适用于数据分析,功能上类似于 excel
,但前者便于复现。使用 pandas
首先要导入库。pandas
是基于 numpy 开发的。
import pandas as pd
目录
数据结构
序列
Series
是一维数组,可以包含任意数据类型,每个数都有一个索引标签。
创建
Series()
函数可以创建序列对象,它的参数可以是列表 、字典或 numpy数组。
s = pd.Series(np.random.randn(3))
# 0 -0.365480
# 1 -0.745080
# 2 -0.107698
# dtype: float64
在默认情况下,第一个元素被标记为 0,第二个元素被标记为 1。可以传入 index
参数指定索引名称,其长度必须与数据长度相同。
pd.Series(['Alice', 42], index=['name', 'age'])
# name Alice
# age 42
# dtype: object
序列的索引可以相同。
当参数为字典时,字典的键即为索引。
d = {'a': 1, 'b': 2}
pd.Series(d)
# a 1
# b 2
# dtype: int64
当字典作为参数,序列排序默认按照字典的排序,如果传入 index
参数,则按照 index
中指定的顺序排序。
pd.Series(d, index=['b', 'a', 'c'])
# b 2.0
# a 1.0
# c NaN
# dtype: float64
标量也可以作为参数。当输入标量时,它会被复制成与 index
长度相同数量的值。
pd.Series(2, index=['a', 'b', 'c'])
# a 2
# b 2
# c 2
# dtype: int64
在创建 Series
时还可以指定 name
,否则将被自动命名。
pd.Series(np.random.randn(3), name='old')
# 0 -0.038295
# 1 0.551865
# 2 1.103370
# Name: old, dtype: float64
属性和方法
index
属性可以获取一个序列的键索引,keys()
方法功能相同。
s.index # Index(['name', 'age'], dtype='object')
s.keys()
Series
的计算方法与 ndarray
类型相似,可以进行运算、切片等操作,详细可以查看 numpy使用。如果需要获得 Series
的值,则使用 array
属性,这样可以忽略掉它的索引。to_numpy()
方法可以把序列转化为 numpy
数组,values
属性功能相同。
s.array
# [-0.36547972911183113, -0.7450803876117753, -0.10769806920146939]
# Length: 3, dtype: float64
s.to_numpy() # array([-0.36547973, -0.74508039, -0.10769807])
s.values
mean()
、min()
、 max()
和 std()
方法可以分别得到序列的平均值、最小值、最大值和标准差。
age = pd.Series([16, 23, 25, 33])
age.mean() # 24.25
age.min() # 16
age.max() # 33
age.std() # 6.994
当数据含有缺失值时,计算得到的结果也将是缺失值,设置 skip_na
参数为 True
可以忽略缺失值从而完成计算。
与
numpy
不同的是,Seriese
操作是要对齐索引标签的,详见下文。
Series
的使用还可以像一个字典,通过索引键获取值。也可以传入键列表,获取多个值。
s = pd.Series(np.random.randn(3), index=['a', 'b', 'c'])
s['a']
s[['a', 'c']]
name
属性可以获取序列名称,rename()
方法可以重命名。
s.name # 'old'
s.rename('new')
# 0 1.599583
# 1 -0.281893
# 2 1.441235
# Name: new, dtype: float64
数据框
数据框是一个二维标签数据结构,可以简单的理解为一张表,也可以理解成序列对象的字典。可以通过行索引和列名对其进行操作。
创建
DataFrame()
方法可以创建数据框,它可以接受一维 numpy
数组字典、列表、字典或序列为参数,或者二维 numpy
数组等。通过字典创建,可以输入 index
参数指定行索引。
pd.DataFrame({'Name': ['Alice', 'Bob'], 'Age': [22, 44]}, index=['007', '009'])
# Name Age
# 007 Alice 22
# 009 Bob 44
通过字典列表创建。
pd.DataFrame([{'Name': 'Alice', 'Age': 24}, {'Name': 'Bob', 'Age': 28}])
# one two three
# first -1.334441 -0.222222 -0.993980
# second 1.015804 -0.273330 -0.625443
通过序列字典创建,还可以输入 columns
参数指定列名
pd.DataFrame({'Name': pd.Series(['Alice', 'Bob'], index=['007', '009']) , 'Age': pd.Series([24, 29], index=['007', '009'])}, index=['007', '009'], columns=["Name", "Age"])
# Name Age
# 007 Alice 24
# 009 Bob 29
通过 numpy
数组创建。
pd.DataFrame(np.random.randn(2, 3), index=['first', 'second'], columns=['one', 'two', 'three'])
# one two three
# first -1.334441 -0.222222 -0.993980
# second 1.015804 -0.273330 -0.625443
属性和方法
index
和 columns
分别查看数据框的行索引和列名。
df.index # Index(['007', '009'], dtype='object')
df.columns # Index(['Name', 'Age'], dtype='object')
shape
函数可以查看数据的大小。
df.shape
可以查看数据的列名,得到的是一个列表。
dtypes
查看每列数据的数据类型。
df.dtypes
T
属性可以实现转置。
df.T
info()
方法可以更详细的查看信息。
df.info()
describe()
函数可以快速得到统计值。
stu = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Age': [22, 44]}, index=['007', '009'])
stu.descirbe()
# Age
# count 2.000000
# mean 33.000000
# std 15.556349
# min 22.000000
# 25% 27.500000
# 50% 33.000000
# 75% 38.500000
# max 44.000000
copy()
方法可以复制一个数据框。
df2 = df.copy()
.values
可以得到 numpy
数组。
df.values
读写文件
csv文件
read_csv
可以读取 csv
文件,第一个参数表示想要读取文件位置和文件名;第二个参数 sep
表示分隔符,默认逗号 ,
;设置 keep_default_na
为 False
可以去掉缺失值,缺失值的地方将被空字符串替代。na_values
参数可以设置缺失值。
df = pd.read_csv('data/gap.tsv', sep='\t')
to_csv()
方法保存为 csv
文件,第一个参数表示要保存文件的位置和文件名,第二个参数 `sep`` 表示分隔符
df.to_csv('data/gap2.tsv', sep='\t')
Excel文件
读取
读取使用 read_excel()
函数。
df = read_excel('filename.xlsx')
该函数还有许多可选参数。
参数 | 含义 | 示例 |
---|---|---|
sheet_name | 表名 | 0, 1, 2, ‘sheet1’, [0, 1, ‘sheet1’] |
header | 表头行号 | 0, None |
names | 指定表头名 | [‘aa’, ‘bb’, ‘cc’] |
index_col | 指定列索引 | None, 0, [0, 1, 3] (多重索引) |
usecols | 使用哪些列 | None, ‘A: C’, ‘A, C’, [0, 1, 3], [‘col1’, ‘col2’] |
写入
如果想要把序列文件保存为 Excel
文件,则首先要使用 to_frame()
方法把序列转化为数据框。
df = ser.to_frame()
to_excel()
方法将数据框写入 Excel
文件。
df.to_excel('new.xlxs')
该函数也有许多可选参数。
参数 | 含义 | 示例 |
---|---|---|
sheet_name | 表名 | ‘sheet1’ |
columns | 要保存的列 | [‘col1’, ‘col2’] |
header | 是否保存表头或重新命名表头 | True, False, [‘new_col1’, ‘new_col2’] |
index | 保存行索引 | True, False |
indel_label | 指定索引的表头名 | ‘suoyin’, [‘suoyin1’, ‘suoyin2’] |
startrow | 表头第一行上方空几行 | 0, 2, 3 |
startcol | 表头第一列左侧空几列 | 0, 2, 3 |
na_rep | 缺失数据表示 | ‘’ |
inf_rep | 无穷数据表示 | ‘inf’ |
float_format | 浮点数格式 | ’%.2f’ |
数据选择
提取列
想要获取一列信息,在方括号 []
内输入想要获取的列名,或者直接用 .
也可以。
name_df = df['name']
df.name
如果想要获取多列,则需要传入一个包含多个列名的列表。
df[['name', 'age']]
提取行
head()
方法和 tail()
方法分别查看数据的前 5 行和后 5 行,输入参数可以指定输出前几行。
df.head() # 前 5 行
df.head(n=1) # 前 1 行
df.tail() # 后 5 行
df.tail(1) # 后 1 行
loc
输入行索引可以得到所需要的行。
df.loc['007'] # 获取行索引为 '007' 的行
iloc
功能相似,输入一个整数,表示第几行。
df.iloc[0] # 获取第 1 行
如果需要获得多行,则需要传入一个列表。也可以通过切片的方式实现。
df.loc[[0, 2, 3]]
df.iloc[[0, 2, 3]]
df[5: 10]
同时操作行和列
同样使用 loc
,方括号内用逗号 ,
分隔,左边表示行索引,右边表示列名。
df.loc[4, 'name']
如果需要提取多行多列,则都需要传入列表。
df.loc[[2, 4], ['name', 'age']]
如果使用 iloc
,则需要输入行号和列号,而不是行索引和列名。
df.iloc[4, 0]
df.iloc[[1, 2], [0, 1]]
增加列
增加列的方法与取列的方法相同,只需要指定列名与值就好。
stu['birthday'] = ['19980110', '19981001']
insert()
方法可以将值插入指定位置,比如要把年份插入到第 1 列。
df.insert(1, 'Year', [1996, 2000])
assign()
方法可以从已有列中派生出新的列。方法也可以作为其参数。
df.assign(new_col=df['Age']+1)
df.assign(new_col=lambda x: x['Age'] + 1)
增加行
要想把一个序列作为一行数据添加到数据集,首先要把序列转化为数据框。然后再用下问拼接的方式实现。
new_row_df = pd.DataFrame([['n1', 'n2', 'n3', 'n4']], columns=['A', 'B', 'C', 'D'])
删除
pop()
方法可以删除一列。
df.pop('Age')
drop()
方法可以删除行或列。首先指定 labels
参数,再指定 axis
删除行或列。
df.drop(labels=['007'], axis=1)
drop_duplicates()
方法可以删除重复的行或列,指定 axis
参数。
df.drop_duplicates()
dropna()
方法删除有空缺数据的行或列。
bool值索引
还可以利用 bool
值作为索引进行过滤。
stu[[True, False]]
# Name Age
# 007 Alice 22
数据拼接
concat()
假设有两个数据框 df1
和 df2
,concat()
函数可以把两个数据框按行进行拼接。
row_concat = pd.concat([df1, df2])
该函数还有 axis
参数,当参数为 0 时(默认),则以添加行的形式拼接;当为 1 时,则以添加列的形式拼接。
拼接后如果需要重新编索引号,则可以把 ingore_index
参数设置为 True
,否则默认为 False
。
append()
还可使使用 append()
方法增加数据。
df1.append(df2)
还可以使用字典,只要主键与数据框列名保持一致,就可以正常拼接。
data_dict = {'A': 'n1', 'B': 'n2', 'C': 'n3', 'D': 'n4'}
df1.append(data_dict, ignore_index=True)
排序
sort_values()
sort_values()用于排序。
df = df.sort_values(by='col', axis=0, ascending=True, inplace=False, kind='quicksort')
参数 by
表示依据哪一列进行排序。
如果想要交换列进行排序,则需要把 axis
参数设为 1。
排序默认为升序,若想为降序则需要把 ascending
设为 False。
inplace
参数表示是否在原表进行排序,默认为 False,原表不变,排序后返回一张新的表。
参数 kind
表示排序方式,可选 quicksort(默认)、mergesort、heapsort、stable。
当值中有 NaN时,默认摆在最后位置,要想放在开头则需要把 na_position
设为 first,否则为 last
。
排序后若想重新设置索引值,则需要把 ingore_index
参数设为 True;否则为 False,使用原来的索引。
sort_index()
该函数与 sort_values()
十分类似,也是排序,但是是基于索引值进行排序,因此没有 sort_values()
函数中的 by
参数,其它参数均一致。
处理缺失值
数据中可能会存在缺失值 np.NaN
,它不等于任何东西。isnull()
函数可以判断是否是缺失值,如果是缺失值,则返回 True
。notnull()
函数可以检查值是否为空,如果是缺失值,则返回 False
。
from numpy import NaN
pd.isnull(NaN) # True
pd.notnull(NaN) # False
统计缺失值
count()
方法可以计算每列的非缺失值数。
df.count() # 每列非缺失值数
可以结合 numpy
库计算有多少缺失值。
import numpy as np
np.count_nonzero(df['Age'].isnull()) # Age 列有多少缺失值
np.count_nonzero(df.isnull()) # 整个数据集有多少缺失值
使用序列的 values_count()
方法针对列中每个不重复数据计算它的个数,它会默认跳过缺失值,如果在 drop_na
参数中传入 False
,即可得到缺失值的个数。
df.Age.values_count(drop_na=False).head()
填充缺失值
fillna()
方法可以填充缺失值,输入我们提供的参数,替换所有的缺失值。
df.fillna(0)
设置 method
参数为 ffill
、bfill
可以分别实现前值填充(用前面的值填充进行填充,如果开头就是缺失值则无法完成填充)、后值填充。interpolate()
方法实现插值填充。
df.fillna(method='ffill')
df.interpolate()
数据对齐和计算
DataFrame
之间的计算是要通过行和列的索引和标签进行对齐的。
df1 = pd.DataFrame(np.random.randn(3, 2), index=['a', 'b', 'c'])
df2 = pd.DataFrame(np.random.randn(4, 3), index=['a', 'b', 'c', 'd'])
df1 + df2
# 0 1 2
# a -0.920320 0.947203 NaN
# b 1.089856 -1.327052 NaN
# c 2.604738 -0.038784 NaN
# d NaN NaN NaN
DataFrame
与 Series
之间的计算是通过广播机制实现的,与标量的计算也是如此。
df1 - df1.iloc[0] # 每行都减去第一行
# 0 1
# a 0.000000 0.000000
# b 1.431525 0.879529
# c 0.207648 -0.617918
df1 + 100 # 每个元素加 100
# 0 1
# a 99.545553 99.951717
# b 100.977078 100.831246
# c 99.753201 99.333800
表连接
join()
表连接类似于数据库的表连接,用 join()
函数,基本用法如下。
df1.join(df2)
该操作直接将 df2 中的列加到 df1 上,相当于做了拼接。
如果想要像数据库那样通过 key 进行连接,则需要让 key 成为表的 index,可以通过 set_index()
函数把列设为 key。
df1.set_index('key')
df2.set_index('key')
df1.join(df2)
或者也可以只把第二个表的 index 设为 key,第一个表不需要设置,使用 on 参数。
df2.set_index('key')
df1.join(df2, on='key')
表的连接方式也有多种选择,使用参数 how
设置。值为 left(默认)时表示使用 df1 的索引,可以理解为左外连接;right 表示使用 df2 的索引,右外连接;outer 为外连接;inner 表示内连接;cross 表示全连接。
merge()
表连接还有一个类似的操作——merge()
,基本用法:
df1.merge(df2)
该方法也有许多可选参数。how 表示连接方式,默认为 inner。
当两个表的主键名相同时,可以直接设置为参数 on,无需把主键设置为表的 index。若名称不同,可分别设置left_on 和 right_on 参数。
展示
当数据行列过多时,中间的行和列会用省略号表示,可以通过设置更改显示方式。to_string()
方法可以返回表的字符串表示。但它无法适应控制台的宽度。
df.to_string()
设置 display.max_colwidth
可以设置每一列的显示宽度。
pd.set_option("display.max_colwidth", 100)