Pandas 基础使用

12 minute read

Published:

Pandas 和 NumPy 有什么不同:如果用 python 的列表和字典来作比较, 那么可以说 Numpy 是列表形式的,没有数值标签,Pandas 就是字典形式,而且 Pandas 是基于 NumPy 构建的。

请注意设置 dtype

请注意设置 inplaceignore_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)

参考资料及致谢

Pandas 官方文档

第二周:numpy和pandas

Python-Pandas 学习 append的效率

Pandas DataFrame的基本属性