python数据分析笔记

文章目录

  • 数据分析-相关笔记
    • 1、matplotlib
      • 1.01、matplotlib折线图
        • 1.01-1、matplotlib基本要点:
        • 1.01-2、 实例1:画出10点到12点每分钟的温度变化
      • 1.02、其他类型图的画法
      • 1.03、绘制多条条形图
    • 2、numpy
      • 2.01、numpy基础
        • 2.01-1、什么是numpy:
        • 2.01-2、numpy创建数组(矩阵):
        • 2.01-3、numpy常见的数据类型
        • 2.01-4、修改数组内数据的类型:
        • 2.01-5、保留小数numpy.round():
      • 2.02、数组的形状和计算
        • 2.02-1、查看数组形状
        • 2.02-2、修改数组形状
        • 2.02-3、数组的计算
        • 2.03-4、广播原则
        • 2.03-5、轴(axis)
      • 2.03、numpy读取数据
      • 2.04、numpy中的数据转置
      • 2.05、numpy索引和切片
      • 2.06、numpy中数值修改
      • 2.07、numpy中的布尔索引
      • 2.09、numpy中的clip(裁剪)
      • 2.10、numpy中的nan和inf
      • 2.11、numpy中的nan的注意点
      • 2.12、numpy中常用的统计函数
      • 2.13、数组的拼接
      • 2.14、数组的行列交换
      • 2.15、numpy更多好用的方法
      • 2.16、numpy生成随机数
      • 2.17、numpy的注意点copy和view
    • 3、pandas
      • 3.01、pandas常用的数据类型
        • 3.01-1、pandas之Series创建
        • 3.01-2、pandas之Series切片和索引
        • 3.01-3、pandas之Series的索引和值
      • 3.02、pandas读取外部数据
      • 3.03、pandas之DataFrame
        • 3.03-1、DataFrame的基础属性
        • 3.03-2、DataFrame整体情况查询
      • 3.04、pandas索引数据
        • 3.04-1、pandas取行或列的注意点
        • 3.04-2、pandas之loc
        • 3.04-3、pandas之iloc
        • 3.04-4、pandas之布尔索引
      • 3.05、缺失数据处理
      • 3.06、pandas的常用统计方法
      • 3.07、数据的离散化案例(统计小说各分类的数量):
      • 3.08、数据合并
        • 3.08-1、数据合并之join
        • 3.08-2、数据合并之merge
      • 3.09、pandas分组和聚合
        • 3.09-1、常见的`DataFrameGroupBy`对象的聚合方法:
      • 3.10、索引和复合索引
        • 3.10-2、符复合索引取值操作
        • 3.10-3、DataFram类型复合索引
        • 3.10-4、Series类型复合索引
        • 3.10-5、取内层索引-索引交换
        • 3.11-1、生成一段时间
        • 3.11-2、关于频率的更多缩写
        • 3.11-3、在DataFrame中使用时间序列
        • 3.11-4、pandas重采样

数据分析-相关笔记

1、matplotlib

1.01、matplotlib折线图

1.01-1、matplotlib基本要点:

from matplotlib import pyplot as plt

# 设置图片大小
plt.figure(figsize=(20,8),dpi=80)
# figure图形图标的意思,在这里指的就是我们画的图
# 通过实例化一个figure并且传递参数,能够在后台自动使用该figure实例
# 在图像模糊的时候可以传入dpi参数,让图片更加清晰。

x = [2,4,6,8,10]
y = [25,16,31,28,26]

# 绘图
plt.plot(x,y)

# 设置x轴的刻度
plt.xticks(x)
# plt.xticks(x[::2]) 当刻度太密集的时候,使用列表的步长来解决。

# 设置y轴的刻度
plt.yticks()

# 保存图片
plt.savefig('./1.png')

# 展示图形
plt.show()
  1. 绘图

    plt.plot(x,y)
    
  2. 设置图片大小

    plt.figure(figsize=(20,8),dpi=80)
    # figure图形图标的意思,在这里指的就是我们画的图
    # 通过实例化一个figure并且传递参数,能够在后台自动使用该figure实例
    # 在图像模糊的时候可以传入dpi参数,让图片更加清晰。
    
  3. 设置x、y轴坐标文字。

    plt.xticks(list(x)[::3],, rotation=90)
    # rotation是这是坐标轴文字显示旋转的状态。rotation=90是旋转90度。
    plt.yticks(y)
    
  4. 设置中文。因为matplotlib默认不显示中文。需要设置。

    • 拷贝微软雅黑或黑体等中文字体文件至如下目录:

      /Users/scrappy_zhang/anaconda3/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/
      
    • 第一种。在Windows和Linux设置字体:通过matplotlib.rc修改

      font = {'family': 'MicroSoft YaHei',
             'weight': 'bold',
              'size': 'larger'}
      matplotlib.rc('font',**font)
      # matplotlib.rc('font', family='MicroSoft YaHei',weight='bold',size='larger')
      
    • 第二种。在Windows、Linux和mac中,通过matplotlib.font_manager修改。

      from matplotlib import font_manager
      my_font = font_manager.FontProperties(fname="字体路径")
      plt.xticks(list(x)[::3],, rotation=90,fontproperties=my_font)
      
  5. 画多个线条。

    font = font_manager.FontProperties('SimHei', size=10)
    
    y1 = [1,0,1,1,2,4,3,2,3,4,4,5,6,5,4,3,3,1,1,1]
    y2 = [1,0,3,1,2,2,3,3,2,1,2,1,1,1,1,1,1,1,1,1]
    x = [i for i in range(11,31)]
    
    plt.plot(x, y1, label='自己')
    plt.plot(x, y2, label='同桌')
    
    # 显示图例
    # 只有这一处使用prop设置字体
    plt.legend(prop=font)
    
  6. 设置图例

    # loc参数可以这是图例的位置,具体可以参考源码
    plt.legend(prop=font, loc=0)
    
  7. 显示网格

    # alpha设置透明度
    plt.grid(alpha=0.2)
    
  8. 设置线条的颜色

    plt.plot(x, y, label='', color='', linestyle='--', linewidth=5, alpha=0.5)
    
    颜色 风格字符
    r 红色 - 实线
    g 绿色 -- 虚线、破折线
    b 蓝色 -. 点划线
    w 白线 : 点虚线、虚线
    留空或空格,无线条
    c 青色
    m 洋红
    y 黄色
    k 黑色
    #00ff00 16进制
    alpha=0.8 灰度值

1.01-2、 实例1:画出10点到12点每分钟的温度变化

import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
from matplotlib import font_manager

# 第一种设置中文显示方式
# font = {'family' : 'SimHei',
#               'weight' : '1',
#               'size'   : '12'}
#
# matplotlib.rc('font', **font)

# 第二种设置中文显示的方式
my_font = font_manager.FontProperties('SimHei')

plt.figure(figsize=(20,8),dpi=100)
x =range(0,120)
y = [random.randint(25,30) for i in range(120)]
plt.plot(x,y)
# 调整x轴的刻度
_xticks = ['10点{}分'.format(i) for i in range(60)]
_xticks += ['11点{}分'.format(i) for i in range(60)]
# 取步长,数字和字符串要一一对应。rotation旋转x轴刻度,竖直显示。
plt.xticks(list(x)[::3],_xticks[::3], rotation=45,fontproperties=my_font)

# 设置xy轴的信息,以及标题信息
plt.xlabel('时间', fontproperties=my_font)
plt.ylabel('温度 单位(℃)', fontproperties=my_font)
plt.title('10点到12点之间每分钟的温度变化', fontproperties=my_font)

# 显示图像
plt.show()

1.02、其他类型图的画法

类型 方法
折线图 matplotlib.pyplot.plot(x,y)
散点图 matplotlib.pyplot.scatter(x,y)
条形图 matplotlib.pyplot.bar(x,y)普通条形图|matplotlib.pyplot.barh(x,y)绘制横向条形图
直方图 matplotlib.pyplot.hist(x,y)

1.03、绘制多条条形图

from matplotlib import pyplot as plt
from matplotlib import font_manager

font = font_manager.FontProperties('SimHei', size=12)
# 设置图片大小
plt.figure(figsize=(20, 8), dpi=80)

# 数据
a = ["星球崛起3:终极之战", "敦刻尔克", "英雄归来", "战狼2"]
b_16 = [15746, 312, 4497, 319]
b_15 = [12357, 156, 2045, 168]
b_14 = [2358, 399, 2358, 362]

# 设置的柱宽
bar_width = 0.2

# 计算图形的间隔
x_14 = list(range(len(a)))
x_15 = [i + bar_width for i in x_14]
x_16 = [i + bar_width for i in x_15]

# 绘制条形图
plt.bar(x_14, b_14, width=bar_width, label='14号')
plt.bar(x_15, b_15, width=bar_width, label='15号')
plt.bar(x_16, b_16, width=bar_width, label='16号')

# 设置x轴的刻度内容
plt.xticks(x_15, a, fontproperties=font)

# 设置图像信息
plt.xlabel('电影名',fontproperties=font)
plt.ylabel('票房 单位(万元)',fontproperties=font)
plt.title('三天票房数据对比',fontproperties=font)


# 设置条形图的数据标签
for a, b in zip(x_14 + x_15 + x_16, b_14 + b_15 + b_16):
    plt.text(a, b + 50, '%.0f万元' % b, fontproperties=font)

# 设置图例
plt.legend(prop=font)

# 显示图像
plt.show()

2、numpy

2.01、numpy基础

2.01-1、什么是numpy:

一个在python中做科学计算的基础库,重在数值计算,也是大部分python科学计算库的基础库,多用在大型、多维数组上执行数值运算。

2.01-2、numpy创建数组(矩阵):

import numpy as np

a = np.array([1,2,3,4,5,6])
b = np.array(range(1,7))
c = np.arange(1,7)
#以上三种方法相同,
#np.arange()的用法:arange([start,] stop[, step,], dtype=None)

2.01-3、numpy常见的数据类型

类型 类型代码 说明
int8、uint8 i1、u1 有符号和无符号的8位(1个字节)整型
int16、uibt16 i2、u2 有符号和无符号的16位(2个字节)整型
int32、uint32 i4、u4 有符号和无符号的32位(4个字节)整型
int64、uint64 i8、u8 有符号和无符号的64位(8个字节)整型
float16 f2 半精度浮点数
float32 f4或f 标准的单精度浮点数。与C的float兼容
float64 f8或d 标准的双精度浮点数。与C的double和python的float对象兼容
float128 f16或g 扩展精度浮点数
complex64、complex128、complex256 c8、c16、c32 分别用两个32位、64位或128位浮点数表示的复数。
bool ? 存储True和Flase值的布尔类型

2.01-4、修改数组内数据的类型:

numpy.astype(float)修改数组的类型

import numpy as np

a = np.array([1,2,3,4,5,6], dtype='i4')
print(a.dtype)
print(a)
b = a.astype(dtype='i8')
print(b.dtype)
print(b)

>int32
>[1 2 3 4 5 6]
>int64
>[1 2 3 4 5 6]

2.01-5、保留小数numpy.round():

np.round(b,2)
#b数组元素保留两位小数

2.02、数组的形状和计算

2.02-1、查看数组形状

import numpy as np

a = np.array([[1,2,3],[4,5,6]])
print(a.shape)

>>(2, 3)  # 两行三列

2.02-2、修改数组形状

  1. reshape():修改数组形状。

    import numpy as np
    
    a = np.array([[1,2,3],[4,5,6]])
    
    # reshape()有返回值,但对数据本身并不会产生影响。除非找一个变量接收返回值。
    # 例如:a.reshape(),会产生新的形状,但a并没有变化。
    b = a.reshape(3,2)
    print(a.shape)
    print(b.shape)
    
  2. 多维数组转换为一维数组(1)。reshape()需要传入一个数据,就是数组元素的个数。

    import numpy as np
    
    a = np.array([[1,2,3],[4,5,6]])
    a = a.reshape((6,))
    
    >>[1 2 3 4 5 6]
    
  3. 多维数组转换为一维数组(2)。

    import numpy as np
    
    a = np.array([[1,2,3],[4,5,6]])
    
    a = a.flatten()
    print(a)
    >>[1 2 3 4 5 6]
    

2.02-3、数组的计算

  1. 数组和数字的运算:数组中的每个元素都和数字进行计算。

  2. 数组和数组的运算:对应位置的元素进行计算。

    • 多维数组和一维数组的计算(示例如下):

      • 1行6列的一维数组可以和多行6列的多维数组进行计算。
      • 6行1列的数组可以和6行多列的多维数组进行计算。
      #要求:一维数组的行或列要与二维数组的行和列个数一致。
      t1 = np.arange(0,6)
      t2 = np.arange(24).reshape(4,6)
      print(t2-t1)
      
      #t1 = np.arange(0,6)
      #t2 = np.arange(24).reshape(6,4)
      #t1 = t1.reshape(6,1)
      #print(t2-t1)
      
      >[[ 0  0  0  0  0  0]
      >[ 6  6  6  6  6  6]
      >[12 12 12 12 12 12]
      >[18 18 18 18 18 18]]
      
    • 多维数组与多维数组的计算

      #如果数组的格式一样,即行和列数量一样。
      #则在对应位置的元素进行计算。
      

2.03-4、广播原则

如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为他们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。

可以把维度理解为shape()所对应的数字个数。

示例:

  1. shape(3,3,3)的数组和(3,2)的数组能进行计算吗?

    不能,(3,3,3)可以理解为数组为3个3行3列,(3,2)是3行2列数组,他们的行列数都不一样,无法对应起来。不能计算。

  2. shape(3,3,2)和(3,2)的数组能计算吗?

    能,(3,3,2)可以理解为数组为3个3行2列,(3,2)是3行2列数组,(3,2)可以在(3,3,2)中对应起来,也就是说后缘维度相符。可以计算。

2.03-5、轴(axis)

在numpy中可以理解为方向,使用0,1,2…数字表示,对于一个一维数组,只有一个0轴,对于2维数组(shape(2,2)),有0轴和1轴,对于三维数组(shape(2,2,3)),有0,1,2轴。

有了轴的概念之后,我们计算会更加方便,比如计算一个2维数组的平均值,必须指定是计算哪个方向上面的数字的平均值。

2.03、numpy读取数据

np.loadtxt(frame,dtype=np.float,delimiter=None,skiprows=0,usecols=None,unpack=False)

参数 解释
frame 文件、字符串或产生器,可以是.gz或bz2压缩文件
dtype 数据类型,可选,CSV的字符串以什么数据类型读入数组中,默认np.float
delimiter 分割字符串,默认是任何空格,改为逗号
skiprows 跳过前xx行,一般跳过第一行表头
usecols 读取指定的列,索引,元组类型
unpack 如果是True,读入属性将分别写入不同的数组变量,False读入数据只写入一个数组变量,默认为False。就是将行数据转换为列数据,行列互换。
import numpy as np

file_path = './test.csv'

res = np.loadtxt(file_path, delimiter=',', dtype='int')
print(res)

2.04、numpy中的数据转置

转置是一种变换,对于numpy中的数组来说,就是在对角线方向交换数据,目的也是为了更方便的去处理数据。以下是三种数据转置的方法。

  1. t1.transpose()

    import numpy as np
    
    t1 = np.arange(24).reshape((4,6))
    print(t1)
    print('*'*100)
    print(t1.transpose())
    
    结果:
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    ****************************************************************************************************
    [[ 0  6 12 18]
     [ 1  7 13 19]
     [ 2  8 14 20]
     [ 3  9 15 21]
     [ 4 10 16 22]
     [ 5 11 17 23]]
    
  2. t1.swapaxes(1,0)

    import numpy as np
    
    t1 = np.arange(24).reshape((4,6))
    print(t1)
    print('*'*100)
    # 交换两个轴
    print(t1.swapaxes(1,0))
    
  3. t1.T

    import numpy as np
    
    t1 = np.arange(24).reshape((4,6))
    print(t1)
    print('*'*100)
    print(t1.T)
    

2.05、numpy索引和切片

  1. 取单行数据(第三行数据)。

    import numpy as np
    
    t1 = np.arange(24).reshape((4,6))
    print(t1[2,:])
    
  2. 取连续行的数据(第2行之后的所有数据)

    import numpy as np
    
    t1 = np.arange(24).reshape((4,6))
    print(t1[1:,:])
    
  3. 取指定行的数据(第1、3、4行的数据)。

    import numpy as np
    
    t1 = np.arange(24).reshape((4,6))
    print(t1[[0,2,3],:])
    
  4. 取单列的数据(第3列的数据)。

    t1[:,2]
    
  5. 取连续列的数据(第2列之后的数据)。

    t1[:,1:]
    
  6. 取指定列的数据(第2,3,5列数据)。

    t1[:,[1,2,4]]
    
  7. 取指定行列的数据(第3行第4列)。

    t1[2,3]
    
  8. 取多行和多列,取第2行到第4行,第3列到第5列的结果.

    取的是行和列交叉的数据。

    t1[1:4,2:5]
    
  9. 取多个不相邻的点

    #第二行第二列
    #第三行第四列
    #第一行第四列
    t1[[1,2,0],[1,3,3]]
    

2.06、numpy中数值修改

  1. 指定位置值的修改。首先通过numpy索引获取到元素,在重新赋值,即可修改数值。

    t1[2:4,3:5] = 0
    
    结果:
    array([[ 0,  1,  2,  3,  4,  5],
           [ 6,  7,  8,  9, 10, 11],
           [12, 13, 14,  0,  0, 17],
           [18, 19, 20,  0,  0, 23]])
    
  2. 大于或小于某个值的修改。小于10的值都修改为3。

    t1[t1<10] = 3
    

2.07、numpy中的布尔索引

t1 = np.arange(24).reshape((4,6))
t1<10

结果:
array([[ True,  True,  True,  True,  True,  True],
       [ True,  True,  True,  True, False, False],
       [False, False, False, False, False, False],
       [False, False, False, False, False, False]])

###2.08、numpy中三元运算符

#t1中小于10的元素修改为0,大于10的元素修改为10
np.where(t1<10,0,10)

2.09、numpy中的clip(裁剪)

#小于10的修改为10,大于20的修改为20
t1.clip(10,20)

2.10、numpy中的nan和inf

注意:nan和inf都是float类型。

nan(NAN,Nan):not a number表示不是一个数字

什么时候会出现nan?

  • 当我们读取本地文件为float时,如果有缺失,就会出现nan。
  • 当做了一个不合适的计算的时候(比如无穷大(inf)减去无穷大)

inf(-inf.inf):infinity.inf表示正无穷,-inf表示负无穷

什么时候会出现inf包括(+inf,-inf)?

  • 比如一个数字除以0,(python中直接会报错,numpy中是一个inf或者-inf)

2.11、numpy中的nan的注意点

  1. 两个nan不相等。

    #nan表示不是一个数字,但并不知道真实值是什么
    np.nan == np.nan
    
    >False
    
  2. np.nan != np.nan—>True

  3. 利用以上特性,判断数组中nan的个数。

    np.count_nonzero(t1!=t1)
    #输出nan的个数
    
  4. np.isnan(t1)

    利用2的特性。

    isnan()判断是否为nan,如果是则返回True。

    np.isnan(t1)
    #在t1数组中nan的位置返回True
    
  5. nan和任何数计算都为nan。

  6. 在一组数据中单纯的把nan替换为0,替换之后均值肯定会变小,所以一般的方式是把缺失的值替换为均值(中值)或者是直接删除有缺失值的一行。

2.12、numpy中常用的统计函数

  1. 求和:

    t1.sum(axis=None)
    
  2. 均值:受离群点的影响较大

    t1.mean(a.axis=None)
    
  3. 中值:

    np.mediant(t.axis=None)
    
  4. 最大值:

    t1.max(axis=None)
    
  5. 最小值:

    t1.min(axis=None)
    
  6. 极值:即最大值和最小值

    np.ptp(t1,axis=None)
    
  7. 标准差(std):

    t1.std(axis=None)
    

    标准差是一组数据平均值分散程度的一种度量。一个较大的标准差,代表大部分数值和其平均值之间差异较大;一个较小的标准差,代表这些数值较接近平均值反映出数据的波动稳定情况,越大表示波动越大,越不稳定。

  8. 默认返回多维数组的全部统计结果,如果指定axis,则返回一个当前轴上的结果。

2.13、数组的拼接

  1. np.vstack((t1,t2)):竖直拼接,列数不变,增加行数。

    import numpy as np
    
    t1 = np.arange(12).reshape(2,6)
    print(t1)
    print('*'*20)
    t2 = np.arange(12,24).reshape(2,6)
    print(t2)
    print('*'*20)
    print(np.vstack((t1, t2)))
    
    结果:
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]]
    ********************
    [[12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    ********************
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    
  2. np.hstack((t1,t2)):水平拼接,行数不变,增加列数。

    import numpy as np
    
    t1 = np.arange(12).reshape(2,6)
    print(t1)
    print('*'*20)
    t2 = np.arange(12,24).reshape(2,6)
    print(t2)
    print('*'*20)
    print(np.hstack((t1, t2)))
    
    结果:
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]]
    ********************
    [[12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    ********************
    [[ 0  1  2  3  4  5 12 13 14 15 16 17]
     [ 6  7  8  9 10 11 18 19 20 21 22 23]]
    

2.14、数组的行列交换

  1. 行交换:

    import numpy as np
    
    t1 = np.arange(24).reshape(4,6)
    print(t1)
    print('*'*20)
    t1[[2,3], :] = t1[[3,2], :]
    print(t1)
    
    结果:
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    ********************
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [18 19 20 21 22 23]
     [12 13 14 15 16 17]]
    
  2. 列交换:

    import numpy as np
    
    t1 = np.arange(24).reshape(4,6)
    print(t1)
    print('*'*20)
    # t1[[2,3], :] = t1[[3,2], :]
    t1[:, [1,3]] = t1[:, [3,1]]
    print(t1)
    
    结果:
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]]
    ********************
    [[ 0  3  2  1  4  5]
     [ 6  9  8  7 10 11]
     [12 15 14 13 16 17]
     [18 21 20 19 22 23]]
    

2.15、numpy更多好用的方法

  1. 获取最大值最小值的位置。
    • np.argmax(t, axis=0),获取每列最大值的位置。
    • np.argmin(t, axis=1),获取每行最小值的位置。
  2. 创建一个全0的数组:np.zeros((3,4))
  3. 创建一个全1的数组:``np.ones((3,4))`
  4. 创建一个对角线为1的正方形数组(方阵):np.eye(3)

2.16、numpy生成随机数

参数 解释
.rand(d0, d1, ...dn) 创建d0-dn维度的均匀分布的随机数数组,浮点数,范围从0-1
.randn(d0, d1, ...dn) 创建d0-dn维度的标准正态分布随机数,浮点数,平均数0,标准差1
.randint(low, high, (shape)) 从给定上下限范围选取随机数整数,范围是low, high,形状是shape
.uniform(low, high, (size)) 参生具有均匀分布的数组,low起始值,high结束值,size形状
.normal(loc, scale, (size)) 从指定正太分布中随机抽取样本,分布中心是loc(概率分布的均值),标准差是scale,形状是size
.seed(s) 随机数种子,s是给定的种子值。因此计算机生成的是伪随机数,所以通过设定相同的随机数种子,可以每次生成相同的随机数

2.17、numpy的注意点copy和view

  1. a=b:完全不复制,a和b互相影响。
  2. a = b[:]:视图的操作,一种切片,会创建新的对象a,但是a的数据完全由b保管,他们两个的数据变化是一致的。
  3. a = b.copy():复制,a和b互不影响。

3、pandas

numpy能够帮助我们处理数值,但是pandas除了处理数值之外(基于numpy),还能够帮助我们处理其他类型的数据。

3.01、pandas常用的数据类型

  1. Series 一维,带标签数组
  2. DataFrame 二维,Series容器
  3. unique()方法去重。

3.01-1、pandas之Series创建

  1. 第一种创建方式。

    index指定索引值,需要注意的是,索引的个数要和容器的个数一致。

    import numpy as np
    import pandas as pd
    t1 = pd.Series(np.arange(6),index=list('abcdef'))
    
    结果:
    a    0
    b    1
    c    2
    d    3
    e    4
    f    5
    dtype: int32
    
  2. 第二种创建方式:利用字典创建。

    temp_dict = {"name":"fdk","age":23,"tel":10086}
    t = pd.Series(temp_dict)
    
    print(t)
    
    结果:
    name      fdk
    age        23
    tel     10086
    dtype: object
    

3.01-2、pandas之Series切片和索引

切片:直接导入start end 或者步长即可。

索引:一个的时候直接传入序号或者index,多个的时候传入序号或者index的列表。

#字典创建的,可以直接像操作字典一样来取值
t['name']

#普通的,可以直接通过索引来取
t[1]

#取连续的多行
t[1:3]

#取不连续的多行
t[[1,3]]或者t[['name','age']]

#通过布尔来取
t[t>4]

3.01-3、pandas之Series的索引和值

  1. t.index:获取Series的所有索引。
  2. t.values:获取Series的所有值。是numpy.ndarray类型。

Series对象本质上由两个数组构成,一个数组构成对象的键(index, 索引),一个数组构成对象的值(values),键–>值

ndarray的很多方法都可以运用与Series类型,比如argmax, clip

Series具有where方法,但是结果和ndarray不同。

3.02、pandas读取外部数据

import pandas as pd

data = pd.read_csv('dogNames2.csv', delimiter=',')
print(data)
print(type(data))

读取的数据是个DataFrame类型的。

3.03、pandas之DataFrame

pd.DataFrame(np.arange(12).reshape(3,4))

结果:
   0  1   2   3
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

DataFrame对象既有行索引,又有列索引。

行索引,表明不同行,横向索引,叫index,0轴,axis=0。

列索引,表明不同列,纵向索引,叫columns,1轴,axis=1。

3.03-1、DataFrame的基础属性

属性名称 含义
df.shape 行数、列数
df.dtypes 列数据类型
df.ndim 数据维度
df.index 行索引
df.columns 列索引
df.values 对象值,二维ndarray数组

3.03-2、DataFrame整体情况查询

方法名称 含义
df.head(3) 显示头部几行,默认5行
df.tail(3) 显示末尾几行,默认5行
df.info() 相关信息概览:行数、列数、列索引、列非空值个数、列类型、内存占用
df.describe() 快速综合统计结果:计数、均值、标准差、最大值、四分数、最小值。

3.04、pandas索引数据

  1. 排序:

    data = df.sort_values(by="排序依据", ascending=False)
    #ascending默认True,即升序排列,改为False即为降序。
    
  2. 选择前20行的Row_Labels这一列。

    df[:20]['Row_Labels']
    

3.04-1、pandas取行或列的注意点

  • 方括号写数组,表示取行,对行进行操作。

    df['Row_Labels']
    
  • 写字符串,表示的取列索引,对列进行操作。

    df[:20]
    

    如果取的单列,则这个单列的数据类型是Series类型。

3.04-2、pandas之loc

df.loc:通过标签索引行数据。

print(t)

#当前DataFrame的内容
   w  x   y   z
a  0  1   2   3
b  4  5   6   7
c  8  9  10  11
#********************************
#选择单行单列
print(t.loc['a','w'])

#输出
0
#********************************
#选择单行多列,多行单列颠倒位置即可
print(t.loc['a',['y','z']])

#输出
y    2
z    3
#********************************
#选择间隔的多行多列
print(t.loc[['a','c'],['x','z']])

#输出
   x   z
a  1   3
c  9  11

#********************************
#选择连续行列的数据
print(t.loc['a':'c',['w','z']])

#输出
   w   z
a  0   3
b  4   7
c  8  11
#冒号在loc中是闭合的,取值包括c
#********************************

3.04-3、pandas之iloc

df.iloc:通过位置获取行数据。

和loc操作一样,只是把标签索引换成了位置下标。

t.iloc[1:, :3]:表示取第二行之后,第四列之前的数据。

无论是loc还是iloc。都可以在取到值后进行重新赋值,即起到了修改数组值的作用。

3.04-4、pandas之布尔索引

注意点:不同条件之间需要使用括号括起来。

  1. 例如:查找使用次数超过800的狗的名字。

    df[df['Count_AnimalName']>800]
    
  2. 例如:查找查找使用次数超过800小于1000的狗的名字。

df[(df['Count_AnimalName']>800)&(df[df['Count_AnimalName']<1000])]
  1. 例如:查找查找使用次数超过800小于1000的狗的名字。

    df[(df['Count_AnimalName']>800)|(df[df['Count_AnimalName']<1000])]
    
  2. 例如:查找查找使用次数超过800名字长度大于4的狗的名字。

    df[(df['Count_AnimalName'].str.len()>4)|(df[df['Count_AnimalName']>800])]
    

    df['Count_AnimalName'].str获取字符串

####3.04-5、pandas之字符串方法

方法 说明
cat 实现元素级的字符串连接操作,可指定分隔符
contains 返回表示各字符串是否含有指定模式的布尔型数组
count 模式的出现次数
endwith、startwith 相当于对各元素执行x.endwith(pattern)或x.startwith(pattern)
findall 计算各字符串的模式列表
get 获取各元素的第i个字符
join 根据指定的分隔符将Series中各元素的字符串连接起来
len 计算各字符串的长度
lower、upper 转换大小写。相当于对各个元素执行x.lower()或x.upper()
match 根据指定的正则表达式对各个元素执行x.match()
pad 在字符串的左边、右边或者左右两边添加空白符
center 相当于pad(size=‘both’)
repeat 重复值。例如,s.str.repeat(3)相当于对各个字符串执行x*3
replace 用指定字符串替换找到的模式
slice 对Series中的各个字符串进行字串截取
spilt 根据分隔符或正则表达式对字符串进行拆分
strip、rstrip、lstrip 去除空白符,包括换行符。相当于对各个元素执行x.strip()、x.rstrip()、x.lstrip()

3.05、缺失数据处理

数据缺失通常有两种情况:

  • 一种是空,None等,在pandas是NaN(和np.nan一样)。
  • 另一种是值为0的。(看情况处理,有时0是有意义的)

判断数据是否为NaN:pd.isnull(t),pd.notnull(t)。两个正好相反。

处理方式:

  • 直接删除NaN所在行:dropna(axix=0, how='any', inplace=False)
    • how默认为any,即只要有NaN就删除,改为all,则是全为NaN才删除。
    • inplace原地修改,如果为True,则说明修改的结果可以直接影响替换原来的值。如果为False,说明不是原地修改,修改的结果不影响原来的数据。
  • 填充数据:t.fillna(t.mean()), t.fillna(t.median()), t.fillna(0)

3.06、pandas的常用统计方法

  1. 例如电影的平均分:

    df['Rating'].mean()
    
  2. 例如导演的人数:

    temp_list = df['Actors'].str.split(',').tolist()
    nums = set([i for j in temp_list for i in j])
    
  3. 例如电影时长的最大值最小值。

    max_runtime = df['Runtime (Minutes)'].max()
    max_runtime_index = df['Runtime (Minutes)'].argmax()
    min_runtime = df['Runtime (Minutes)'].min()
    min_runtime_index = df['Runtime (Minutes)'].argmin()
    runtime_median = df['Runtime (Minutes)'].median()
    

3.07、数据的离散化案例(统计小说各分类的数量):

首先创建一个全0的二维数组,列名为分类,然后遍历每部小说,将小说对应的分类位置置为1。最后再统计每类的1的数量即可。

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import font_manager

data = pd.read_csv('xiaoshuo.csv', delimiter=',')
# 获取分类的列表
df = data['classify'].tolist()

# 获取不重复的分类
df_clo = set(df)

# 创建一个全0的数组
zeros = pd.DataFrame(np.zeros((data.shape[0], len(df_clo))), columns=df_clo)

# 将小说对应的分类置为1
for i in range(data.shape[0]):
    zeros.loc[i, df[i]] = 1

# 统计各分类的小说数量
count = zeros.sum(axis=0)

# 按照数量进行排序
count_sort = count.sort_values(ascending=False)

# 设置中文字体
font = font_manager.FontProperties('SimHei', size=13)
# 设置图像大小
plt.figure(figsize=(10,5), dpi=80)

# 获取分类名称和对应的数量
_x = count_sort.index
_y = count_sort.values

# 画图
plt.bar(range(len(_x)), _y, width=0.5, color='c')

# 设置对应的刻度
plt.xticks(range(len(_x)), _x, fontproperties=font)
plt.ylim((0,15))

# 在图像中显示数量
for a, b in enumerate(_y):
    plt.text(a-0.2, b+0.5, '共{}部'.format(int(b)), fontproperties=font)

plt.grid(alpha=0.5)
plt.show()

3.08、数据合并

3.08-1、数据合并之join

join:默认的情况下他是把行索引相同的数据合并到一起。

注意:t1.join(t2)。所有的行数索引以前面一个数组为准,即以t1为准,t2少的行,增加上,值置为NaNt2多的行直接剔除。

即:合并后的数组的index索引,以join前面的数组索引为标准。

t1的数据:
   A  B   C   D
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

t2的数据
   E  F
0  0  1
1  2  3
2  4  5
  1. t1.join(t2):结果

       A  B   C   D  E  F
    0  0  1   2   3  0  1
    1  4  5   6   7  2  3
    2  8  9  10  11  4  5
    
  2. t2.join(t1):结果

       E  F  A  B   C   D
    0  0  1  0  1   2   3
    1  2  3  4  5   6   7
    2  4  5  8  9  10  11
    

3.08-2、数据合并之merge

merge:按照指定的列索引把数据按照一定的方式合并到一起。

#数据准备

In [42]: t1
Out[42]:
     M    N  O    P
A  1.0  1.0  a  1.0
B  1.0  1.0  b  1.0
C  1.0  1.0  c  1.0


In [62]: t2
Out[62]:
     V    W  X    Y    Z
A  0.0  0.0  c  0.0  0.0
B  0.0  0.0  d  0.0  0.0
  1. 默认的合并方式inner,交集

    In [66]: t1.merge(t2, left_on="O", right_on="X")
    Out[66]:
         M    N  O    P    V    W  X    Y    Z
    0  1.0  1.0  c  1.0  0.0  0.0  c  0.0  0.0
    
    # inner是默认的合并方式。
    
    In [66]: t1.merge(t2, left_on="O", right_on="X", how="inner")
    Out[66]:
         M    N  O    P    V    W  X    Y    Z
    0  1.0  1.0  c  1.0  0.0  0.0  c  0.0  0.0
    
  2. merge outer,并集,缺失部分NaN补全

    In [67]: t1.merge(t2, left_on="O", right_on="X", how="outer")
    Out[67]:
         M    N    O    P    V    W    X    Y    Z
    0  1.0  1.0    a  1.0  NaN  NaN  NaN  NaN  NaN
    1  1.0  1.0    b  1.0  NaN  NaN  NaN  NaN  NaN
    2  1.0  1.0    c  1.0  0.0  0.0    c  0.0  0.0
    3  NaN  NaN  NaN  NaN  0.0  0.0    d  0.0  0.0
    
  3. merge left:以左边的数组为参考

    In [68]: t1.merge(t2, left_on="O", right_on="X", how="left")
    Out[68]:
         M    N  O    P    V    W    X    Y    Z
    0  1.0  1.0  a  1.0  NaN  NaN  NaN  NaN  NaN
    1  1.0  1.0  b  1.0  NaN  NaN  NaN  NaN  NaN
    2  1.0  1.0  c  1.0  0.0  0.0    c  0.0  0.0
    
  4. merge right:以右边的数组为参考

    In [69]: t1.merge(t2, left_on="O", right_on="X", how="right")
    Out[69]:
         M    N    O    P    V    W  X    Y    Z
    0  1.0  1.0    c  1.0  0.0  0.0  c  0.0  0.0
    1  NaN  NaN  NaN  NaN  0.0  0.0  d  0.0  0.0
    

参数解析:

  • left_on:指定左边数组的列索引。
  • right_on:指定右边数组的列索引。
  • how:选择连接方式,交、并或左、右参考。

3.09、pandas分组和聚合

在pandas中类似的分组的操作有很简单的方法

grouped = df.groupby(by='columns_name')

#grouped是一个DataFrameGroupBy对象,是可迭代的。
#可以调用聚合方法
#grouped中的每一个元素是一个元组
#元组里面是(索引(分组的值),分组之后的DataFrame)

for i,j in grouped:
    print(i,j)
    #i是国家分组,j是DataFrame对象,是这个国家的店铺的数据。

3.09-1、常见的DataFrameGroupBy对象的聚合方法:

函数名 说明
count 分组中非NA值的数量
sum 非NA值的和
mean 非NA值的平均值
median 非NA值的算术中位数
std、var 无偏(分母为n-1)标准差和方差
min、max 非NA值的最小值和最大值

####3.09-2、多条件分组

grouped = df['Brand'].groupby(by=[df['Country'],df['State/Province']]).count()

#获取分组之后的某一部分数据。
#grouped = df.groupby(by=[df['Country'],df['State/Province']])['Brand'].count()
#对某几列数据进行分组。
#grouped = df.groupby(by=[df['Country'],df['State/Province']]).count()['Brand']

#以上写法结果相同。

print(type(grouped))

返回的数据类型是Series

如果想要返回的数据是DataFrame类型呢?

#只需要在取列的时候,用两个方括号括起来即可:df[['Brand']]
grouped = df[['Brand']].groupby(by=[df['Country'],df['State/Province']]).count()
#其他的和Series一样。

多条件分组,返回的数前两列都是索引,即复合索引。

3.10、索引和复合索引

####3.10-1、简单的索引操作

  • 获取indexdf.index
  • 指定indexdf.index = ['x','y']
  • 重新设置indexdf.reindex(list('abcdef')),重新设置的index如果原来没有,就默认值为NaN,而且reindex并不会影响df本身的内容,除非重新赋值给df。
  • 指定某一列的值作为indexdf.set_index('Country', drop=False),drop默认为True,即将作为索引的列从列中删除。如果想要继续保留这列,则设为False。
  • 指定index的唯一值:df.set_index('Country').index_unique(),因为索引是可以重复的,所以unique去重。

3.10-2、符复合索引取值操作

a数组

In [126]: a
Out[126]:
   a  b    c  d
0  0  7  one  h
1  1  6  one  j
2  2  5  one  k
3  3  4  two  l
4  4  3  two  m
5  5  2  two  n
6  6  1  two  o

3.10-3、DataFram类型复合索引

DataFram的复合索引需要使用loc进行定位元素。

数组b = a.set_index(['c','d']):结果为:

#这时,数组的数据类型是DataFrame
In [130]: b
Out[130]:
       a  b
c   d
one h  0  7
    j  1  6
    k  2  5
two l  3  4
    m  4  3
    n  5  2
    o  6  1
  • 如果想要取one,k对应的b列的值。b.loc['one'].loc['j','b']

3.10-4、Series类型复合索引

数组c = b['a']:结果为:

In [135]: c
Out[135]:
c    d
one  h    0
     j    1
     k    2
two  l    3
     m    4
     n    5
     o    6
Name: a, dtype: int64
  • c['one']['j']
  • c['one','j']

3.10-5、取内层索引-索引交换

In [162]: c.index
Out[162]:
MultiIndex(levels=[['one', 'two'], ['h', 'j', 'k', 'l', 'm', 'n', 'o']],
           labels=[[0, 0, 0, 1, 1, 1, 1], [0, 1, 2, 3, 4, 5, 6]],
           names=['c', 'd'])
  • level:相当于索引的内外层。
  • swaplevel()就是交换内外层索引位置。

swaplevel()可以将复合索引进行交换。将内层索引换到外层,再进行取值。

数组d = a.set_index(['d','c'])['a']:结果为:

In [143]: d
Out[143]:
d  c
h  one    0
j  one    1
k  one    2
l  two    3
m  two    4
n  two    5
o  two    6
Name: a, dtype: int64
  • one对应的值:swaplevel()交换水平的索引。d.swaplevel()后和b格式一样。就可以直接取了。

    取内层索引

    In [150]: d.swaplevel()['one']
    Out[150]:
    d
    h    0
    j    1
    k    2
    Name: a, dtype: int64
    

###3.11、时间序列

3.11-1、生成一段时间

pd.date_range(start=None,end=None,periods=None,freq='D')
#periods表示时间段,生成的时间个数
#freq表示时间的频率。年月日等
  • startend以及freq配合能够生成startend范围内以频率freq的一组时间索引。

  • startperiods以及freq配合能够生成从start开始的频率为freqperiods个时间索引。

3.11-2、关于频率的更多缩写

别名 偏移量类型 说明
D Day 每个日历日
B BusinessDay 每个工作日
H Hour 每小时
T或min Minute 每分
S Second 每秒
Lms Milli 每毫秒(即千分之一秒)
U Micro 每微秒(即每百万分之一秒)
M MonthEnd 每月最后一个日历日
BM BusinessMonthEnd 每月最后一个工作日
MS MonthBegin 每月第一个日历日
BMS BusinessMonthBegin 每月第一个工作日

3.11-3、在DataFrame中使用时间序列

In [14]: index = pd.date_range('20181123',periods=10)

In [15]: df = pd.DataFrame(np.random.rand(10),index=index)
    

结果:
In [16]: df
Out[16]:
                   0
2018-11-23  0.273883
2018-11-24  0.171428
2018-11-25  0.262788
2018-11-26  0.483741
2018-11-27  0.215211
2018-11-28  0.361931
2018-11-29  0.696446
2018-11-30  0.241175
2018-12-01  0.227588
2018-12-02  0.855655
  1. 时间字符串转换为时间序列

    df['timeStramp'] = pd.to_datetime(df['timeStramp'],format='')
    
    • format参数大部分情况下可以不用写,但是对于pandas无法格式化的时间字符串,我们可以使用该参数,比如包含中文的。

3.11-4、pandas重采样

重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样。

pandas提高了一个resample的方法来帮助我们实现频率转化。

  1. t.resample(‘M’).mean()

  2. t.resample(‘10D’).count()

####3.11-5、PeriodIndex时间段转换

之前的DatetimeIndex可以理解为时间戳,你们PeriodIndex可以理解为时间段。

可以把分开的、零散的时间字符串通过PeriodIndex的方法进行组合,转化为pandas的时间序列。

periods = pd.PeriodIndex(year=data['year'],month=data['month'],day=data['day'],hour=data['hour'],freq='H')

如果给这个时间段降采样呢?

data = df.set_index(periods).resample('10D').mean()

你可能感兴趣的:(数据分析,python)