(没写完)[第11天] Python Pandas 数据分析 速通爆肝


数据集下载

下载地址:晚点更新

Pandas 介绍

Pandas是基于Numpy构建的。含有使数据分析工作变得更快更简单的高级数据结构和操作工具。它提供了大量高级的数据结构和对数据处理的方法。pandas 有两个主要的数据结构:Series 和 DataFrame

描述性分析

描述性分析用于描述定量数据的整体情况,例如研究消费者对于某商品的购买意愿情况,可用到描述性分析对样本的年龄、收入、消费水平等各指标进行初步分析,以了解掌握消费者总体的特征情况。

描述分析应用场景

通过描述性分析计算数据的集中性特征(平均值)和波动性特征(标准差值),以了解数据的基本情况。因此在研究中经常是首先进行描述性分析,再次基础之上再进行深入的分析。

描述性分析还可用于查看数据是否有异常情况(最小值或最大值查看),比如数据中出现-2,-3等异常情况。

常见的描述指标

  • 最大值、最小值可用来检验数据是否存在异常情况。
  • 平均值、中位数是用于描述数据的集中趋势指标。
  • 标准差是用于描述数据的离散趋势指标。如果比较单位不同(或数值相差太大)的两组数据时,采用变异系数比较离散程度。
  • 峰度和偏度通常用于判断数据正态性情况,峰度的绝对值越大,说明数据越陡峭,峰度的绝对值大于3,意味着数据严重不正态。同时偏度的绝对值越大,说明数据偏斜程度越高,偏度的绝对值大于3,意味着严重不正态(可通过正态图查看数据正态性情况)

其他说明

1、一般采用平均值加标准差来描述数据的整体情况。

2、当数据呈现严重偏态时,采用中位数描述数据的整体水平情况,而不是平均值。

3、除了使用描述性分析外,也建议使用箱线图直观展示数据分布情况。

Series和DataFrame

Series

Series是一种类似于一维数组的对象。它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。可以把它理解为一组带索引的数组

将Python 字典转换成Series

# ^ 将 Python 字典转换成 Series 对象
dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
obj = pd.Series(dic)
print(obj)

当没有显示指定索引的时候,Series 自动以 0 开始,步长为 1 为数据创建索引。

通过 index 参数显示指定索引

# ^ 通过 index 参数显示指定索引
obj2 = pd.Series([4, 5, 6, 7], index=['a', 'b', 'c', 'd'])
print(obj2)

对于 Series 对象里的单个数据来说,和普通数组一样,根据索引获取对应的数据或重新赋值

不过你还可以传入一个索引的数组来获取数据或未数据重新赋值

# ^ 获取数据 修改数据
print("获取 a=", obj2['a'])
print("获取 a、c Series\n", obj2[['a', 'c']])
# @ 修改数据
obj2['a'] = 10
obj2[['b', 'c']] = 20
print(obj2)

想要单独获取 Series 对象的索引或者数组内容的时候,可以使用 index 和 values 属性

# ^ 单独获取 Series 对象的索引或者数组内容的时候,可以使用 index 和 values 属性
print(obj2.index)
print(obj2.values)

# ^ 对 Series 对象的运算(索引不变)
print("Series 对象的运算")
obj3 = pd.Series([10, 20, 30, 40])
print(obj3*2)
print(obj3+1)
print(obj3[obj3 < 30])
print(obj3[obj3 > 10])

Dataframe

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

例如将一个由 NumPy 数组组成的字典转换成 DataFrame 对象

# ! Dataframe
# ^ 将numpy数组字典转换成dataframe对象
data = {'name': ['小王', '小刘', '小能', '小张'], 'age': [30, 40, 20, 30], 'gender': ['m', 'm', 'm', 'f']}
frame = pd.DataFrame(data)
print(frame)

指定列的顺序

# ^ 指定列的顺序
frame = pd.DataFrame(data, columns=['name', 'gender', 'age'])
print(frame)
  如果传入的列名找不到,它不会报错,而是产生一列 NA 值
# ^ 如果传入的列名找不到,它不会报错,而是产生一列 NA 值:
frame = pd.DataFrame(data, columns=['name', 'gender', 'age', 'weight'])
print(frame)
  DataFrame 不仅可以以字典索引的方式获取数据,还可以以属性的方法获取
# ^ DataFrame 不仅可以以字典索引的方式获取数据,还可以以属性的方法获取
print(frame['name'])
print(frame.name)

修改数据

# ^ 修改列的数据
frame['weight'] = 60
print(frame)
# @ 删除一列
del frame['weight']
print(frame)

什么是NaN数据

在能够使用大型数据集训练学习算法之前,我们通常需要先清理数据。也就是说,我们需要通过某个方法检测并更正数据中的错误。虽然任何给定数据集可能会出现各种糟糕的数据,例如离群值或不正确的值,但是我们几乎始终会遇到的糟糕数据类型是缺少值。Pandas 会为缺少的值分配 NaN 值

处理NaN数据

统计NaN个数

import pandas as pd
import numpy as np

# ^ 创建一个字典数组
items2 = [{'bikes': 20, 'pants': 30, 'watches': 35, 'shirts': 15, 'shoes': 8, 'suits': 45},
          {'watches': 10, 'glasses': 50, 'bikes': 15, 'pants': 5, 'shirts': 2, 'shoes': 5, 'suits': 7},
          {'bikes': 20, 'pants': 30, 'watches': 35, 'glasses': 4, 'shoes': 10}]

# ^ 创建一个dataFrame对象,指定索引
store_items = pd.DataFrame(items2, index=['store 1', 'store 2', 'store 3'])

print(store_items)

可以看到有缺省的值被替换成了NaN,创建的 DataFrame 具有 3 个 NaN 值:商店 1 中有一个,商店 3 中有两个。但是,如果我们向 DataFrame 中加载非常庞大的数据集,可能有数百万条数据,那么就不太容易直观地发现 NaN 值的数量。对于这些情形,我们结合使用多种方法来计算数据中的 NaN 值的数量。以下示例同时使用了 .isnull()sum() 方法来计算我们的 DataFrame 中的 NaN 值的数量。

# ^ 计算 dataframe 有多少 NaN 值
x =  store_items.isnull().sum().sum()
# @ 第一次sum()算出各个列有几个,第二次算出全部

print('共有NaN值:', x)

# 共有NaN值: 3

在上述示例中,.isnull() 方法返回一个大小和 store_items 一样的布尔型 DataFrame,并用 True 表示具有 NaN 值的元素,用 False 表示非 NaN 值的元素。

# ^ isnull()方法返回一个大小和store_items一样的布尔型 DataFrame
frame = store_items.isnull()
print(frame)

在 Pandas 中,逻辑值 True 的数字值是 1,逻辑值 False 的数字值是 0。因此,我们可以通过数逻辑值 True 的数量数出 NaN 值的数量。为了数逻辑值 True 的总数,我们使用 .sum() 方法两次。要使用该方法两次,是因为第一个 sum() 返回一个 Pandas Series,其中存储了列上的逻辑值 True 的总数,如下所示:
数非 NaN 值的数量可以使用 .count() 方法
# ^ 数非 NaN 值的数量。可以使用 .count() 方法
print(store_items.count())

处理NaN值

我们有两种选择,可以删除或替换 NaN

从 DataFrame 中删除包含任何 NaN 值的行或列。如果 axis = 0,.dropna(axis) 方法将删除包含 NaN 值的任何行,如果 axis = 1.dropna(axis) 方法将删除包含 NaN 值的任何列。
# ! 处理NaN
# ^ 删除含NaN的行
frame = store_items.dropna(axis=0)  # inplace = True 对结构直接进行修改
print(frame)

# ^ 删除含NaN的列
frame = store_items.dropna(axis=1)
print(frame)

注意,.dropna() 方法不在原地地删除具有 NaN值的行或列。也就是说,原始 DataFrame 不会改变。你始终可以在 dropna() 方法中将关键字 inplace 设为 True,在原地删除目标行或列。 可以选择将所有 NaN 值替换为 0。可以使用 .fillna() 方法
# @ 替换NaN的值
# ^ 把所有NaN的值替换为0
frame = store_items.fillna(0)
print(frame)
我们还可以使用 .fillna() 方法将 NaN 值替换为 DataFrame 中的上个值,称之为前向填充。在通过前向填充替换 NaN 值时,我们可以使用列或行中的上个值。.fillna(method = 'ffill', axis) 将通过前向填充 (ffill) 方法沿着给定 axis 使用上个已知值替换 NaN 值。
# ^ 把一行所有的NaN的值填充为上一行的值
frame = store_items.fillna(method='ffill', axis=0)
print(frame)

# ^ 把一行所有的NaN的值填充为前一列的值
frame = store_items.fillna(method='ffill', axis=1)
print(frame)

同样,你可以选择用 DataFrame 中之后的值替换 NaN 值,称之为后向填充。.fillna(method = 'backfill', axis) 将通过后向填充 (backfill) 方法沿着给定 axis 使用下个已知值替换 NaN 值。和前向填充一样,我们可以选择使用行值或列值。
# ^ 向后填充
frame = store_items.fillna(method='backfill', axis=0)
print(frame)

注意,.fillna() 方法不在原地地替换(填充)NaN 值。也就是说,原始 DataFrame 不会改变。你始终可以在 fillna() 函数中将关键字 inplace 设为 True,在原地替换 NaN 值。
我们还可以选择使用不同的插值方法替换 NaN 值。例如,.interpolate(method = 'linear', axis) 方法将通过 linear 插值使用沿着给定 axis 的值替换 NaN 值。
# ^ 使用线性插值替换
frame = store_items.interpolate(method='linear', axis=1)
print(frame)

什么是聚合数据

合并来自不同数据源的数据,强调把分散在不同地方关于同一对象的不同说法合并起来,得到此对象的更为完整的信息。

合并来自不同数据源的数据

pandas 读取 csv

csv 介绍

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。

read_csv 函数解析

read_csv(filepath_or_buffer,sep,header,names,skiprows,na_values,encoding,nrows)   按指定格式读取csv文件.   filepath_or_buffer:字符串,表示文件路径;   sep: 字符串,指定分割符,默认是',';   header:数值, 指定第几行作为列名(忽略注解行),如果没有指定列名,默认header=0; 如果指定了列名header=None;   names: 列表,指定列名,如果文件中不包含header的行,应该显性表示header=None.   skiprows:列表,需要忽略的行数(从0开始),设置的行数将不会进行读取.   na_values:列表,设置需要将值替换成NAN的值,pandas默认NAN为缺省,可以用来处理一些缺省,错误的数值.   encoding:字符串,用于unicode的文本编码格式.例如,"utf-8"或"gbk"等文本的编码格式.   nrows:需要读取的行数.

to_csv 函数解析

to_csv(path_or_buf,sep,na_rep,columns,header,index)   path_or_buf:字符串,文件名,文件具体,相对路径,文件流等;   sep:字符串,文件分割符号;   na_rep:字符串,将NaN转换为特定值;   columns:列表,选择部分列写入;   header:None,写入时忽略列名;   index:False则选择不写入索引,默认为True.

csv 库(扩展)

csv.reader(csvfile, dialect=‘excel’, **fmtparams)
csv.writer(csvfile, dialect=‘excel’, **fmtparams)

csvfile,必须是支持迭代(Iterator)的对象,可以是文件(file)对象或者列表(list)对象,如果是文件对
象,打开时需要加"b"标志参数。
qdialect,编码风格,默认为excel的风格,也就是用逗号(,)分隔,dialect方式也支持自定义
fmtparam,格式化参数,用来覆盖之前dialect对象指定的编码风格。

代码

import pandas as pd
import numpy as np
import os

# ^ 获取当前终端目录
path = os.getcwd()
# ^ 获取当前文件目录
path = os.path.dirname(__file__)

# ^ 读取 csv 操作
df = pd.read_csv(path+r'\iris.csv', header=None, names=['花蕾长', '花蕾宽', '花瓣长', '花瓣宽', '类别'])

"""
函数解析:
read_csv(filepath_or_buffer,sep,header,names,skiprows,na_values,encoding,nrows)
按指定格式读取csv文件.
filepath_or_buffer:字符串,表示文件路径;
sep: 字符串,指定分割符,默认是',';
header:数值, 指定第几行作为列名(忽略注解行),如果没有指定列名,默认header=0; 如果指定了列名header=None;
names: 列表,指定列名,如果文件中不包含header的行,应该显性表示header=None.
skiprows:列表,需要忽略的行数(从0开始),设置的行数将不会进行读取.
na_values:列表,设置需要将值替换成NAN的值,pandas默认NAN为缺省,可以用来处理一些缺省,错误的数值.
encoding:字符串,用于unicode的文本编码格式.例如,"utf-8"或"gbk"等文本的编码格式.
nrows:需要读取的行数.
"""
# @ 输出前三项数据
print(df.head(3))

# ^ 写入 csv 操作

filePath = path + r'\test.csv'

data = {
    'name': ['小王', '小张', '小刘'],
    'age': [10, 20, 30]
}

# @ 将字典转换成DataFrame数据结构类型
df = pd.DataFrame(data)

# @ 将DataFrame结构保存为csv文件
df.to_csv(filePath)

"""
函数解析:
  to_csv(path_or_buf,sep,na_rep,columns,header,index)
  path_or_buf:字符串,文件名,文件具体,相对路径,文件流等;
  sep:字符串,文件分割符号;
  na_rep:字符串,将NaN转换为特定值;
  columns:列表,选择部分列写入;
  header:None,写入时忽略列名;
  index:False则选择不写入索引,默认为True.
"""

Pandas 读取 TSV

什么是 TSV

TSV 是Tab-separated values的缩写,即制表符分隔值。
Python的csv模块准确的讲应该叫做dsv模块,因为它实际上是支持范式的分隔符分隔值文件(DSV,delimiter-separated values)的。
delimiter参数值默认为半角逗号,即默认将被处理文件视为CSV。
delimiter='\t'时,被处理文件就是TSV。

代码

import pandas as pd
import os

# ^ 获取当前文件目录
path = os.path.dirname(__file__)

# ^ 读取 tsv 操作
# IMPORTANT 这里用到了 sep = '\t'
df = pd.read_csv(path+'/realEstate_trans.tsv', sep='\t')

print(df.head(3))

# ^ 保存 tsv 操作
filePath = path + r'\test.tsv'

data = {
    'name': ['小王', '小张', '小刘'],
    'age': [10, 20, 30]
}

# @ 转换成 dataframe 结构
df = pd.DataFrame(data)

# @ 添加间隔符\t,禁止保存索引
df.to_csv(filePath, sep='\t', index=False)

Pandas 读取 JSON

json存在的目的是为了跨语言交换数据

read_json 函数

read_json(path_or_buf,orient,encoding,numpy)   常见参数解析:   path_or_buf:字符串,表示文件路径;   orient:指示预期的JSON字符串格式.可以to_json()使用相应的方向值生成兼容的JSON字符串.一组可能的方向是:
  'split' : dict like {index -> [index], columns -> [columns], data -> [values]}
  'records' : list like [{column -> value}, ... , {column -> value}]
  'index' : dict like {index -> {column -> value}}
  'columns' : dict like {column -> {index -> value}}
  'values' : just the values array
  encoding:字符串,默认为'utf-8';   numpy:布尔值,默认为False,直接解码为numpy数组.仅支持数字数据,但支持非数字列和索引标签.另请注意,如果numpy = True,则每个术语的JSON顺序必须相同.

to_json 函数

to_json(path_or_buf,orient,encoding,index)   前三个参数和read_json()里的一样   index:False则选择不写入索引,默认为True.

代码

import pandas as pd
import os

# ^ 获取当前文件目录
path = os.path.dirname(__file__)

# ^ 读取 json 操作
df = pd.read_json(path+'/films.json')

"""
read_json(path_or_buf,orient,encoding,numpy)
  常见参数解析:
  path_or_buf:字符串,表示文件路径;
  orient:指示预期的JSON字符串格式.可以to_json()使用相应的方向值生成兼容的JSON字符串.一组可能的方向是:
  'split' : dict like {index -> [index], columns -> [columns], data -> [values]}
  'records' : list like [{column -> value}, ... , {column -> value}]
  'index' : dict like {index -> {column -> value}}
  'columns' : dict like {column -> {index -> value}}
  'values' : just the values array
  encoding:字符串,默认为'utf-8';
  numpy:布尔值,默认为False,直接解码为numpy数组.仅支持数字数据,但支持非数字列和索引标签.另请注意,如果numpy = True,则每个术语的JSON顺序必须相同.
"""

print(df.head(3))

# ^ 写入 json 操作
filePath = path + r'\test.tsv'

data = {
    'name': ['小王', '小张', '小刘'],
    'age': [10, 20, 30]
}

# @ 转换成 dataframe 结构
df = pd.DataFrame(data)

# @ 添加间隔符\t,禁止保存索引
df.to_json(filePath)

"""
  to_json(path_or_buf,orient,encoding,index)
  前三个参数和read_json()里的一样
  index:False则选择不写入索引,默认为True.
"""

loads、dumps(扩展)

先放放