Pandas 基础使用
Published:
Pandas 和 NumPy 有什么不同:如果用 python 的列表和字典来作比较, 那么可以说 Numpy 是列表形式的,没有数值标签,Pandas 就是字典形式,而且 Pandas 是基于 NumPy 构建的。
请注意设置 dtype
请注意设置 inplace
和 ignore_index
在 notebook 中需要显示所有数据设置 pd.set_option('display.max_rows', None)
Series
Series 是一种类似于以为 NumPy 数组的对象,它由一组数据(各种 NumPy 数据类型)和与之相关的一组数据标签(即索引)组成的。可以用 index 和 values 分别规定索引和值。如果不规定索引,会自动创建 0 到 N-1 索引。
构建 Series
# 用 list 直接创建 pd.Series
# 设置 index,用 index 索引
# 设置 name,相当于 DataFrame 中的列名 columns
# 设置 dtype: 'int64', 'float64'
s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'], name='test', dtype='int64')
print (s1)
"""
a 1
b 2
c 3
Name: test, dtype: int64
"""
# 用字典直接创建 pd.Series,可以索引 index
dic = {'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
s2 = pd.Series(dic, index=['b','c','d'])
print(s2)
"""
b [4, 5, 6]
c [7, 8, 9]
dtype: object
"""
# 用 Series 创建 pd.Series,可以索引 index
s3 = pd.Series(s1, index=['b','c','d'])
print(s3)
"""
b 2.0
c 3.0
d NaN
dtype: float64
"""
# name 属性, 可以起名字
s1.name = 'test'
s1.index.name = 'key'
print(s1)
"""
key
a 1
b 2
c 3
Name: test, dtype: int64
"""
# pd.Series 的索引可以修改(注意索引数组长度与原来的要一致,修改后索引的 name 丢失)
s1.index = ['x','y','z']
print(s1)
"""
x 1
y 2
z 3
Name: test, dtype: int64
"""
索引
s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
"""
a 1
b 2
c 3
dtype: int64
"""
# 根据位置提取相应的值
print(s1[0]) # 1
# 根据 index 提取相应的值
print(s1['a']) # 1
缺失数据
s1 = pd.Series([np.nan, 2, 3], index=['a', 'b', 'c'])
"""
a NaN
b 2.0
c 3.0
dtype: float64
"""
# pd.isnull() 和 pd.notnull() 是用来检测缺失数据
print(pd.isnull(s1))
"""
a True
b False
c False
Name: test, dtype: bool
"""
# inplace=False,默认该删除操作不改变原数据,而是返回一个执行删除操作后的新 dataframe;
# inplace=True,则会直接在原数据上进行删除操作
s1.dropna(inplace=True)
print(s1)
"""
b 2.0
c 3.0
dtype: float64
"""
基本运算
# pd.Series 按照键值自动对齐功能, 对齐后按照 index 的名字进行行排序
s1 = pd.Series([1, 2, 3], index=['x','y','z'])
s2 = pd.Series([10,20,30,40], index = ['x','y','z','i'])
print(s1 + s2)
"""
i NaN
x 11.0
y 22.0
z 33.0
dtype: float64
"""
DataFrame
DataFrame 是一种表格型结构,含有一组有序的列,每一列可以是不同的数据类型。既有行索引,又有列索引,可以被看做由 Series 组成的字典(使用共同的索引)。
构建 DataFrame
# 用 list 直接创建 pd.DataFrame
df1 = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'], index=['one','two'])
print (df1)
"""
a b
one 1 2
two 3 4
"""
# 用字典直接创建 pd.DataFrame
data = {'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
df2 = pd.DataFrame(data)
print(df2)
"""
a b c
0 1 4 7
1 2 5 8
2 3 6 9
"""
# 可以有空列,可以索引 columns, 可以重新设置 index
df3 = pd.DataFrame(data, columns=['a', 'c', 'b', 'e'], index=['one', 'two', 'three'])
print(df3)
"""
a c b e
one 1 7 4 NaN
two 2 8 5 NaN
three 3 9 6 NaN
"""
# 用 DataFrame 直接创建 pd.DataFrame,可以索引 columns 和 index
df4 = pd.DataFrame(df2, columns=['a','c','b','e'], index=[1, 2])
print(df4)
"""
a c b e
1 2 8 5 NaN
2 3 9 6 NaN
"""
# 输出其 index columns valuses
print(df3.index) # Index(['one', 'two', 'three'], dtype='object')
print(df3.columns) # Index(['a', 'c', 'b', 'e'], dtype='object')
print(df3.values)
"""
[[1 7 4 nan]
[2 8 5 nan]
[3 9 6 nan]]
"""
DataFrame 信息
df1 = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'], index=['one','two'])
# 查看数据值列的汇总统计:变量数量、平均值、方差、分位数、最大最小值
df1.describe()
"""
a b
count 2.000000 2.000000
mean 2.000000 3.000000
std 1.414214 1.414214
min 1.000000 2.000000
25% 1.500000 2.500000
50% 2.000000 3.000000
75% 2.500000 3.500000
max 3.000000 4.000000
"""
# 查看数据信息:行列信息、数据类型、缺失值个数、内存大小
df1.info()
"""
<class 'pandas.core.frame.DataFrame'>
Index: 2 entries, one to two
Data columns (total 2 columns):
a 2 non-null int64
b 2 non-null int64
dtypes: int64(2)
memory usage: 48.0+ bytes
"""
排序
# 升序
df1.sort_values('col_name', ascending=False)
# 降序
df1.sort_values('col_name', ascending=True)
索引
data = {'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
df1 = pd.DataFrame(data, columns=['a', 'c', 'b', 'e'], index=['one', 'two', 'three'])
"""
a c b e
one 1 7 4 NaN
two 2 8 5 NaN
three 3 9 6 NaN
"""
# 根据 columns 来选择数据
print(df1['a'])
print(df1.a)
"""
one 1
two 2
three 3
Name: a, dtype: int64
"""
# 根据 columns 来选择多列数据
print(df1[['a', 'b']])
# 根据 columns 来选择数据 loc()
print(df1.loc[:, 'a'])
"""
one 1
two 2
three 3
Name: a, dtype: int64
"""
# 根据 index 来选择数据 loc()
print(df1.loc['two'])
"""
a 2
c 8
b 5
e NaN
Name: two, dtype: object
"""
# 根据 index 和 columns 来选择数据 loc()
print(df1.loc['two', ['a','b']])
"""
a 2
b 5
Name: two, dtype: object
"""
# 采用位置来选择数据 iloc()
print(df1.iloc[1,:])
"""
a 2
c 8
b 5
e NaN
Name: two, dtype: object
"""
print(df1.iloc[:,1])
"""
one 7
two 8
three 9
Name: c, dtype: int64
"""
print(df1.iloc[1:,:2])
"""
a c
two 2 8
three 3 9
"""
print(df1.iloc[0,2]) # 4
# 混合这两种的方法 ix()
print(df1.ix[1:, ['a', 'b']])
"""
a b
two 2 5
three 3 6
"""
print(df1.ix[['one','two'], :1])
"""
a
one 1
two 2
"""
# 通过判断筛选
print(df1[frame1.a > 1])
"""
a c b e
two 2 8 5 NaN
three 3 9 6 NaN
"""
赋值
data = {'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
df1 = pd.DataFrame(data, columns=['a', 'c', 'b', 'e'], index=['one', 'two', 'three'])
"""
a c b e
one 1 7 4 NaN
two 2 8 5 NaN
three 3 9 6 NaN
"""
# 根据行列和位置可以直接选出来重新赋值即可
df1['d'] = pd.Series([100,200,300],index = ['two','one','three'])
print(df1)
"""
a c b e d
one 1 7 4 NaN 200
two 2 8 5 NaN 100
three 3 9 6 NaN 300
"""
# 对行赋值
# 注意 index 一定不能少 如果少了你会发现 赋值完了全部都是 NaN
df1.loc['two'] = pd.Series([1,11,111,1111], index=['a','b','c','d'])
print(df1)
"""
a c b e d
one 1.0 7.0 4.0 NaN 200.0
two 1.0 111.0 11.0 NaN 1111.0
three 3.0 9.0 6.0 NaN 300.0
"""
# 还可以根据位置设置 loc iloc 条件等来赋值
df1.iloc[0,2] = 999
print(df1)
"""
a c b e d
one 1.0 7.0 999.0 NaN 200.0
two 1.0 111.0 11.0 NaN 1111.0
three 3.0 9.0 6.0 NaN 300.0
"""
# 重命令列名或行名
df1.rename(columns={'a': 's'}, index={'one': 'five'}, inplace=True)
print(df1)
"""
s c b e d
five 1.0 7.0 999.0 NaN 200.0
two 1.0 111.0 11.0 NaN 1111.0
three 3.0 9.0 6.0 NaN 300.0
"""
# 重置索引,drop 为 False 则索引列会被还原为普通列,否则会丢失
df1.reset_index(drop=True, inplace=True)
print(df1)
"""
s c b e d
0 1.0 7.0 999.0 NaN 200.0
1 1.0 111.0 11.0 NaN 1111.0
2 3.0 9.0 6.0 NaN 300.0
"""
删除
data = {'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
df1 = pd.DataFrame(data, columns=['a', 'c', 'b', 'e'], index=['one', 'two', 'three'])
"""
a c b e
one 1 7 4 NaN
two 2 8 5 NaN
three 3 9 6 NaN
"""
# 注意是否需要 inplace
df1.drop(index=['one', 'two'], inplace=True)
print(df1)
"""
a c b e
three 3 9 6 NaN
"""
df1.drop(columns=['a'], inplace=True)
print(df1)
"""
c b e
three 9 6 NaN
"""
缺失数据
data = {'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}
df1 = pd.DataFrame(data, columns=['a', 'c', 'b', 'e'], index=['one', 'two', 'three'])
df1.iloc[0, 0] = np.nan
"""
a c b e
one 1 7 4 NaN
two 2 8 5 NaN
three 3 9 6 NaN
"""
# isnull() 和 notnull() 是用来检测缺失数据
print(df1.isnull())
"""
a c b e
one True False False True
two False False False True
three False False False True
"""
# 检测在数据中是否存在 NaN, 如果存在就返回 True:
print(np.any(df1.isnull())) # True
# 如果想直接去掉有 NaN 的行或者列,可以直接用 dropna
df1.dropna(
axis=0, # 0: 对行进行操作,删行; 1: 对列进行操作,删列
subset=["a"], # 只看 subset 是否有 NaN 值,删行看列,删列看行
how='any', # 'any': 只要存在 NaN 就 drop 掉; 'all': 必须全部是 NaN 才 drop
inplace=True
)
print(df1)
"""
a c b e
two 2.0 8 5 NaN
three 3.0 9 6 NaN
"""
# 缺失值补零
df1.fillna(0, inplace=True)
# 缺失值采用前项填充或后向填充,对于一整列都是 NaN 的情况无效
df1.fillna(method="ffill", inplace=True) # 用前面的值填充后面的,第一个就是 NaN 不变
df1.fillna(method="bfill", inplace=True) # 用后面的值填充前面的,最后一个就是 NaN 不变
# 计算每列的均值或中位数进行填充,对于一整列都是 NaN 的情况无效
df1.fillna({'a':df1['a'].median(), 'c':df1['c'].mean()})
算术运算
s1 = pd.Series([1, 2, 3], ['a', 'b', 'c'])
s2 = pd.Series([4, 5, 6], ['b', 'c', 'd'])
print(s1 + s2)
"""
a NaN
b 6.0
c 8.0
d NaN
dtype: float64
"""
df1 = pd.DataFrame(np.arange(12.).reshape(3,4),columns=list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape(4,5),columns=list('abcde'))
print(df1)
"""
a b c d
0 0.0 1.0 2.0 3.0
1 4.0 5.0 6.0 7.0
2 8.0 9.0 10.0 11.0
"""
print(df2)
"""
a b c d e
0 0.0 1.0 2.0 3.0 4.0
1 5.0 6.0 7.0 8.0 9.0
2 10.0 11.0 12.0 13.0 14.0
3 15.0 16.0 17.0 18.0 19.0
"""
print(df1 + df2) # 任何数加 NaN,结果还是 NaN
"""
a b c d e
0 0.0 2.0 4.0 6.0 NaN
1 9.0 11.0 13.0 15.0 NaN
2 18.0 20.0 22.0 24.0 NaN
3 NaN NaN NaN NaN NaN
"""
# add() sub() div() mul() 函数
print(df1.add(df2, fill_value = 100)) # 原来 NaN 的地方用 fill_value 填充,之后再进行运算
合并 concat
推荐使用 concat。
df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'])
df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])
df3 = pd.DataFrame(np.ones((3,4))*2, columns=['a','b','c','d'])
# axis 合并方向,ignore_index 重置 index
# concat 纵向合并
res = pd.concat([df1, df2, df3], axis=0, ignore_index=True)
print(res)
"""
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 1.0 1.0 1.0 1.0
4 1.0 1.0 1.0 1.0
5 1.0 1.0 1.0 1.0
6 2.0 2.0 2.0 2.0
7 2.0 2.0 2.0 2.0
8 2.0 2.0 2.0 2.0
"""
# concat 横向合并
# 当 ignore_index 为 True 时 columns 自动被重置
res1 = pd.concat([df1, df2, df3], axis=1, ignore_index=True)
print(res1)
"""
0 1 2 3 4 5 6 7 8 9 10 11
0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
1 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
2 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
"""
res2 = pd.concat([df1, df2, df3], axis=1, ignore_index=False)
print(res2)
"""
a b c d a b c d a b c d
0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
1 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
2 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 2.0 2.0 2.0
"""
# join (合并方式)
df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'], index=[1,2,3])
df2 = pd.DataFrame(np.ones((3,4))*1, columns=['b','c','d','e'], index=[2,3,4])
#纵向"外"合并 df1 与 df2
res = pd.concat([df1, df2], axis=0, join='outer')
print(res)
"""
a b c d e
1 0.0 0.0 0.0 0.0 NaN
2 0.0 0.0 0.0 0.0 NaN
3 0.0 0.0 0.0 0.0 NaN
2 NaN 1.0 1.0 1.0 1.0
3 NaN 1.0 1.0 1.0 1.0
4 NaN 1.0 1.0 1.0 1.0
"""
#纵向"内"合并 df1 与 df2
res = pd.concat([df1, df2], axis=0, join='inner')
print(res)
"""
b c d
1 0.0 0.0 0.0
2 0.0 0.0 0.0
3 0.0 0.0 0.0
2 1.0 1.0 1.0
3 1.0 1.0 1.0
4 1.0 1.0 1.0
"""
添加 append
pandas 提供的 append 方法效率过低,建议先转为 list 后,再直接使用 append。
而且 append 只能能在 axis=0 上进行合并,推荐使用 concat。
# append 是 concat 的简略形式,只不过只能在 axis=0 上进行合并
df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'])
df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])
df3 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])
s1 = pd.Series([1,2,3,4], index=['a','b','c','d'])
# 将 df2 合并到 df1 的下面,以及重置 index,并打印出结果
res = df1.append(df2, ignore_index=True)
print(res)
"""
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 1.0 1.0 1.0 1.0
4 1.0 1.0 1.0 1.0
5 1.0 1.0 1.0 1.0
"""
# 合并多个 df,将 df2 与 df3 合并至 df1 的下面
res = df1.append([df2, df3], ignore_index=True)
print(res)
"""
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 1.0 1.0 1.0 1.0
4 1.0 1.0 1.0 1.0
5 1.0 1.0 1.0 1.0
6 1.0 1.0 1.0 1.0
7 1.0 1.0 1.0 1.0
8 1.0 1.0 1.0 1.0
"""
# 合并 series,将 s1 合并至 df1
res = df1.append(s1, ignore_index=True)
print(res)
"""
a b c d
0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0
3 1.0 2.0 3.0 4.0
"""
匹配合并 merge
import pandas as pd
# how: inner, outer, left, right, cross
df3 = pd.merge(df1, df2, how='outer', left_on='col_name', right_on='col_name')
导入和导出数据
import pandas as pd
import numpy as np
import csv
df = pd.DataFrame(np.arange(12).reshape(3, 4), index=['one', 'two', 'three'], columns=['a', 'b', 'c', 'd'])
"""
a b c d
one 0 1 2 3
two 4 5 6 7
three 8 9 10 11
"""
# 保存到 csv
df.to_csv(
"demo.csv", # 文件名
columns=['a', 'b', 'c', 'd'], # columns: 指定需要存储的列
header=True, # header: 是否把 columns 写入 CSV 文件,
index=False, # 是否把 index 写入 CSV 文件
encoding='utf-8' # 编码,中文乱码可以用 'gbk'
)
#从csv中读数据
names = ['A','B','C','D'] # 列的名称
data = pd.read_csv(
"demo.csv", # 文件名
names=names, # 指定新的列名
header=0, # CSV 中列名所在的行
skiprows=1, # 要跳过前 n 行,这里跳过第一行
delimiter=',', # 分隔符
encoding='utf-8' # 编码,中文乱码可以用 'gbk'
)
print(data)