数据分析(2) Pandas基本结构

  Pandas主要有两种数据结构:SeriesDataFrame

  (1)Series:类似于一维数组的对象,由数据(各种NumPy数据类型)以及与之相关标签(索引)组成。仅由一组数据也可产生简单的Series对象。注意:Series中的索引值是可以重复的。

  (2)DataFrame:表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。

  引入方式:from pandas import Series, DataFrame 或 import pandas as pd 

1 Series

  1.1 创建方式

  (1)通过列表创建:默认索引值,元组方式与列表相同

  (2)通过数组创建:默认索引值,由于内置默认问题,数据类型与列表生成的会不一样

  (3)通过字典创建:键值做索引

import pandas as pd
import numpy as np
list0 = [87, 90, 89]
tuple0 = (87, 90, 89)
dict0 = {‘语文‘: 87, ‘数学‘: 90, ‘英语‘: 89}
ser1 = pd.Series(list0)
ser2 = pd.Series(tuple0)
ser3 = pd.Series(np.array(list0))
ser4 = pd.Series(dict0)
print(‘===== 列表创建 =====\n‘, ser1)
print(‘===== 元组创建 =====\n‘, ser2)
print(‘===== 数组创建 =====\n‘, ser3)
print(‘===== 字典创建 =====\n‘, ser4)# ===== 列表创建 =====
#  0    87
# 1    90
# 2    89
# dtype: int64
# ===== 元组创建 =====
#  0    87
# 1    90
# 2    89
# dtype: int64
# ===== 数组创建 =====
#  0    87
# 1    90
# 2    89
# dtype: int32
# ===== 字典创建 =====
#  语文    87
# 数学    90
# 英语    89
# dtype: int64

  通过列表和数组创建的序列采用默认索引值,可通过index属性更改,如下例,ser1通过更改索引可变为与ser4相同的序列。

ser1.index = [‘语文‘, ‘数学‘, ‘英语‘]
print(‘ser1更改索引后:\n‘, ser1)# ser1更改索引后:
#  语文    87
# 数学    90
# 英语    89
# dtype: int64

  也可创建时同步定义index属性,如下所示:ser1、ser4、ser5生成数组相同

ser5 = pd.Series(list0, index=[‘语文‘, ‘数学‘, ‘英语‘])
print(‘列表创建时指定索引值:\n‘, ser5)# 列表创建时指定索引值:
#  语文    87
# 数学    90
# 英语    89
# dtype: int64 

  1.2 基本操作

  1.2.1 赋值

  Series对象本身以及索引都具有一个name属性,默认为空,根据需要可以进行赋值操作

scores = pd.Series({‘Tom‘: 89, ‘John‘: 88, ‘Merry‘: 96, ‘Max‘: 65})
scores.name = ‘语文‘
scores.index.name = ‘考试成绩‘
print(scores)# 考试成绩
# Tom      89
# John     88
# Merry    96
# Max      65
# Name: 语文, dtype: int64

  1.2.2 查询

  Series获取多个值的方式类似NumPy中的ndarray的切片操作,主要有两种方式:

  (1)[索引]:读取对应索引的数据,包含右侧索引

  (2)[下标]:读取对应下标值的数据,不包括右侧下标

scores = pd.Series({‘Tom‘: 89, ‘John‘: 88, ‘Merry‘: 96, ‘Max‘: 65})
print(‘===== 通过索引 =====\n‘, scores[‘Tom‘:‘Merry‘])
print(‘===== 通过下标 =====\n‘, scores[0:3])# ===== 通过索引 =====
#  Tom      89
# John     88
# Merry    96
# dtype: int64
# ===== 通过下标 =====
#  Tom      89
# John     88
# Merry    96
# dtype: int64

  1.2.3 运算

  Series保留了NumPy中的数组运算,并且进行数组运算的时候,索引与值之间的映射关系不会发生改变。

  注意:在操作Series时,基本上可以把Series看成NumPy中的ndarray数组来进行操作。ndarray数组的绝大多数操作都可以应用到Series上。

  当多个series对象之间进行运算的时候,如果不同series之间具有不同的索引值,那么运算会自动对齐相同索引值的数据,不同索引值赋值为NaN

s1 = pd.Series([12, 23, 45], index=[‘p1‘, ‘p2‘, ‘p3‘])
s2 = pd.Series([54, 43, 32, 21], index=[‘p2‘, ‘p3‘, ‘p4‘, ‘p5‘])
print(‘===== s1 + s2 =====\n‘, s1+s2)# ===== s1 + s2 =====
#  p1     NaN
# p2    77.0
# p3    88.0
# p4     NaN
# p5     NaN
# dtype: float64

  1.2.4 缺失值操作

  对于新建的index没有赋值时,Pandas会给定一个默认值NaN

scores1 = pd.Series({‘Tom‘: 89, ‘John‘: 88, ‘Merry‘: 96, ‘Max‘: 65})
new_index = [‘Tom‘, ‘Max‘, ‘Joe‘, ‘John‘, ‘Merry‘]
scores2 = pd.Series(scores1, new_index)
print(‘===== 原序列 =====\n‘, scores1)
print(‘===== 更改索引后序列 =====\n‘, scores2)# ===== 原序列 =====
#  Tom      89
# John     88
# Merry    96
# Max      65
# dtype: int64
# ===== 更改索引后序列 =====
#  Tom      89.0
# Max      65.0
# Joe       NaN
# John     88.0
# Merry    96.0
# dtype: float64

Pandas中的isnullnotnull两个函数可以用于在Series中检测缺失值,这两个函数的返回时一个布尔类型的Series

print(pd.isnull(scores2))
# Tom      False
# Max      False
# Joe       True
# John     False
# Merry    False
# dtype: bool
print(scores2[pd.isnull])  # 过滤出缺失值项
# Joe   NaN
# dtype: float64 

2 DataFrame

  数据帧是二维数据结构,即数据以行列表格方式排列。

  功能特点:潜在的列是不同数据类型;大小可变;标记轴(行和列)可以对行列执行算术运算。

  2.1创建方式

  pandas.DataFrame(data, index, columns, dtype, copy) 

  (1通过维数组创建:可在创建的时候命名indexcolumns

arr = np.array([
    [‘Tom‘, 76],
    [‘Gerry‘, 98],
    [‘John‘, 85]])
df01 = pd.DataFrame(arr)
df02 = pd.DataFrame(arr, index=[1, 2, 3], columns=[‘姓名‘, ‘成绩‘])
print(‘===== 数组直接创建 =====\n‘, df01)
print(‘===== 重定义行列属性 =====\n‘, df02)# ===== 数组直接创建 =====
#         0   1
# 0    Tom  76
# 1  Gerry  98
# 2   John  85
# ===== 重定义行列属性 =====
#        姓名  成绩
# 1    Tom  76
# 2  Gerry  98
# 3   John  85

  (2)通过字典方式创建:字典的value必须是长度相等的序列或一个标量,不可创建时命名indexcolumns要通过更改自身indexcolunms属性实现

dic = {    # value必须是长度相等的序列或一个标量
    ‘语文‘: [70, 80, 90],
    ‘数学‘: [80, 88, 90],
    ‘英语‘: [80, 78, 88]
}
df01 = pd.DataFrame(dic)
print(‘===== 字典直接创建 =====\n‘, df01)
# df02 = pd.DataFrame(dic, index=[‘one‘, ‘two‘, ‘three‘], columns=[‘a‘, ‘b‘, ‘c‘])    # 该方法等同于增加,不可行
df01.index = [‘one‘, ‘two‘, ‘three‘]    # 通过改变自身属性
df01.columns = [[‘a‘, ‘b‘, ‘c‘]]
print(‘===== 重定义行列属性 =====\n‘, df01)# ===== 字典直接创建 =====
#     语文  数学  英语
# 0  70  80  80
# 1  80  88  78
# 2  90  90  88
# ===== 重定义行列属性 =====
#          a   b   c
# one    70  80  80
# two    80  88  78
# three  90  90  88

  2.2 数据获取

  2.2.1 列数据

  通过列索引, eg: df[column_name],若选择多列,column_name为列名组成的列表[]

df03 = pd.DataFrame(np.random.randint(1, 9, (3, 3)), index=list(‘ABC‘), columns=list(‘abc‘))
print(‘===== 数据结构 =====\n‘, df03)
print(‘===== 列选择 =====\n‘, df03[[‘a‘, ‘b‘]])
df03[‘d‘] = [1, 2, 3]
print(‘===== 列添加 =====\n‘, df03)
# df03.pop(‘d‘)
del df03[‘d‘]
print(‘===== 列删除 =====\n‘, df03)# ===== 数据结构 =====
#     a  b  c
# A  5  6  2
# B  2  4  6
# C  6  3  7
# ===== 列选择 =====
#     a  b
# A  5  6
# B  2  4
# C  6  3
# ===== 列添加 =====
#     a  b  c  d
# A  5  6  2  1
# B  2  4  6  2
# C  6  3  7  3
# ===== 列删除 =====
#     a  b  c
# A  5  6  2
# B  2  4  6
# C  6  3  7

  2.2.2 行数据

loc行名索引,iloc行的数字下标索引

print(‘===== loc 选择行 =====\n‘, df03.loc[‘A‘])
print(‘===== loc 选择某行某列 =====\n‘, df03.loc[‘A‘:‘B‘, ‘b‘:‘c‘])
print(‘===== iloc 选择行 =====\n‘, df03.iloc[1])
print(‘===== iloc 选择某行某列 =====\n‘, df03.iloc[1:3, 1:3])# ===== loc 选择行 =====
#  a    2
# b    8
# c    4
# Name: A, dtype: int32
# ===== loc 选择某行某列 =====
#     b  c
# A  8  4
# B  8  5
# ===== iloc 选择行 =====
#  a    6
# b    8
# c    5
# Name: B, dtype: int32
# ===== iloc 选择某行某列 =====
#     b  c
# B  8  5
# C  6  2

  新增与修改行的方法可参照列操作,删除行要使用drop()方法,带返回值,axis为1表示删除列,0表示删除行。

df03 = df03.drop(‘C‘)
print(‘===== 删除行 =====\n‘, df03)# ===== 删除行 =====
#     a  b  c
# A  4  8  4
# B  6  8  5

  通过DataFrame的相关方式可以获取对应的列或者数据形成一个新的DataFrame, 方便后续进行统计计算

  缺省值:对于DataFrame/Series中的NaN一般采取的方式为删除对应的列/行或者填充一个默认值

  2.2.3 缺省值处理

方法

说明

dropna

根据标签的值中是否存在缺失数据对轴标签进行过滤(删除),可以通过阈值的调节对缺失值的容忍度

fillna

用指定值或者插值的方式填充缺失数据,比如: ffill或者bfill

isnull

返回一个含有布尔值的对象,这些布尔值表示那些值是缺失值NA

notnull

isnull的否定式

  (1)删除 dropna

df = pd.DataFrame([
    [‘Tom‘, np.nan, 456.67, ‘M‘],
    [‘Merry‘, 34, 456.67, np.nan],
    [‘Gerry‘, np.nan, np.nan, np.nan],
    [‘John‘, 23, np.nan, ‘M‘],
    [‘Joe‘, 18, 385.12, ‘F‘],
    [np.nan, np.nan, np.nan, np.nan]],
    columns=[‘name‘, ‘age‘, ‘salary‘, ‘gender‘])
df1 = df.dropna()   # 默认删除包含nan的行
df2 = df.dropna(axis=1)     # 删除包含nan的列
df3 = df.dropna(how=‘all‘)  # 删除所有元素为nan的行或列
print(‘===== 原数据 =====\n‘, df)
print(‘===== 删除包含nan的行 =====\n‘, df1)
print(‘===== 删除包含nan的列 =====\n‘, df2)
print(‘===== 删除所有元素为nan的行或列 =====\n‘, df3)# ===== 原数据 =====
#      name   age  salary gender
# 0    Tom   NaN  456.67      M
# 1  Merry  34.0  456.67    NaN
# 2  Gerry   NaN     NaN    NaN
# 3   John  23.0     NaN      M
# 4    Joe  18.0  385.12      F
# 5    NaN   NaN     NaN    NaN
# ===== 删除包含nan的行 =====
#    name   age  salary gender
# 4  Joe  18.0  385.12      F
# ===== 删除包含nan的列 =====
#  Empty DataFrame
# Columns: []
# Index: [0, 1, 2, 3, 4, 5]
# ===== 删除所有元素为nan的行或列 =====
#      name   age  salary gender
# 0    Tom   NaN  456.67      M
# 1  Merry  34.0  456.67    NaN
# 2  Gerry   NaN     NaN    NaN
# 3   John  23.0     NaN      M
# 4    Joe  18.0  385.12      F

  (2)填充

print(‘===== 用0填充数据中的nan =====\n‘, df.fillna(0))
print(‘===== 用0替换数据中的nan =====\n‘, df.replace({np.nan: 0}))# ===== 用0填充数据中的nan =====
#      name   age  salary gender
# 0    Tom   0.0  456.67      M
# 1  Merry  34.0  456.67      0
# 2  Gerry   0.0    0.00      0
# 3   John  23.0    0.00      M
# 4    Joe  18.0  385.12      F
# 5      0   0.0    0.00      0
# ===== 用0替换数据中的nan =====
#      name   age  salary gender
# 0    Tom   0.0  456.67      M
# 1  Merry  34.0  456.67      0
# 2  Gerry   0.0    0.00      0
# 3   John  23.0    0.00      M
# 4    Joe  18.0  385.12      F
# 5      0   0.0    0.00      0

  2.2.4 排序

  (1)按索引排序

sort_index 对行或列索引进行排序。ascending 参数用于控制升序或降序,默认为升序。

ser = pd.Series(np.arange(0, 4), index=[list(‘bcda‘)])
print(‘===== 原数据 =====\n‘, ser)
print(‘===== 升序 =====\n‘, ser.sort_index())
print(‘===== 降序 =====\n‘, ser.sort_index(ascending=False))# ===== 原数据 =====
#  b    0
# c    1
# d    2
# a    3
# dtype: int32
# ===== 升序 =====
#  a    3
# b    0
# c    1
# d    2
# dtype: int32
# ===== 降序 =====
#  d    2
# c    1
# b    0
# a    3
# dtype: int32

  在 DataFrame 上,sort_index(axis=0, ascending=True) 方法多了一个轴向的选择参数

df = pd.DataFrame(np.random.randint(1, 9, (4, 4)),
                  columns=list(‘bcad‘),
                  index=list(‘BDAC‘))
print(‘===== 原数据 =====\n‘, df)
print(‘===== 升序 =====\n‘, df.sort_index(axis=1))
print(‘===== 降序 =====\n‘, df.sort_index(axis=1, ascending=False))# ===== 原数据 =====
#     b  c  a  d
# B  5  2  3  8
# D  7  3  6  1
# A  8  7  5  8
# C  6  5  4  2
# ===== 升序 =====
#     a  b  c  d
# B  3  5  2  8
# D  6  7  3  1
# A  5  8  7  8
# C  4  6  5  2
# ===== 降序 =====
#     d  c  b  a
# B  8  2  5  3
# D  1  3  7  6
# A  8  7  8  5
# C  2  5  6  4 

  (2)按值排序

  作用:既可以根据列数据,也可根据行数据排序。
  注意: 必须指定by参数,即必须指定哪几行或哪几列;无法根据index名和columns名排序(由.sort_index()执行)

  Series按值进行排序, 排序时,任何缺失值默认都会被放到Series的末尾

print(‘===== 通过值排序 =====\n‘, ser.sort_values())
print(‘===== 通过列值排序 =====\n‘, df.sort_values(by=[‘d‘, ‘b‘]))
print(‘===== 通过行值排序 =====\n‘, df.sort_values(by=‘B‘, axis=1, ascending=False))# ===== 通过值排序 =====
#  b    0
# c    1
# d    2
# a    3
# dtype: int32
# ===== 通过列值排序 =====
#     b  c  a  d
# B  6  7  8  3
# C  3  5  8  4
# A  3  1  7  7
# D  4  7  7  8
# ===== 通过行值排序 =====
#     a  c  b  d
# B  8  7  6  3
# D  7  7  4  8
# A  7  1  3  7
# C  8  5  3  4

相关推荐