Python数据分析第一周总结

Python数据分析第一周总结

一、数据分析的介绍

1.什么是指标?

指标:能够反映业务特征的统计数据就是指标。

Database —> DB —> OLTP (Online Transation Procession) —> 业务库

Logging日志文件—>Flume/Logstash

开发数据集 —> CSV/Excel/Open API —> JSON —>Sqoop

ETL —> Extract Transform Load

Data warehouse —>DW —> OLAP(Online Analysis Processing) —> 分析库

​ —> Hadoop (HDFS + MapReduce/Spark) —>Hive —>HQL

2.数据分析的工作内容

1.确定目标(输入)

2.获取数据

3.清洗数据

4.数据透视

5.数据报告(输出)

6.分析洞察(后续)

3.工具准备

Jupyter —> Julia / Python / R

​ — Notebook

​ — JupyterLab

Anaconda —>Python 3.9 + 200个三方库(小白)

Miniconda —> Python 3.9 + 若干个必要的库

方案一:

打开电脑终端

输入命令pip install jupyter 下载jupyter

输入命令jupyter notebook,启动jupyter notebook

如果jupyter notebook无法执行代码,输入命令pip install pyzmp==20.0.0

方案二:

下载jupyterlab输入命令pip install jupyterlab

更新jupyterlab输入命令pip install -U jupyterlab

运行jupyterlab输入命令jupyter lab

4.常用魔法指令

%pwd显示文件路径

%ls看到该路径下所有文件

%lsmagic看所有的魔法指令

%load导入该路径下的某个python文件

二、认识Notebook

for _ in range(10):
    print('hello ,world')
# 查看函数的用法
? range
# 显示文件的路径
%pwd
# 显示当前文件
%ls
# 查看所有的魔法指令
%lsmagic

热身练习

用随机的方式产生5个学生(姓名自拟)3门课程(语文、数学、英语)的成绩

1.统计每个学生的平均分。

2.统计每门课程的最高分和最低分。

3.统计每门课程成绩的(样本)方差。

def average(scores: list):
    return sum(scores) / len(scores)

def variance(scores: list):
    mean_value = average(scores)
    return sum([(score-mean_value)**2 for score in scores]) / (len(scores)-1)
import random

names = ('Sam', 'Mary', 'Bob', 'Alex', 'Alice')
courses = ('语文', '数学', '英语')
scores = [[random.randrange(0, 101) for x in range(3)] for y in range(5)]
scores
for i, name in enumerate(names):
    print(f'{name}平均分:{average(scores[i]):.1f}')
for i, course in enumerate(courses):
    temp_scores = [scores[j][i] for j in range(5)]
    print(f'{course}的最高分:{max(temp_scores)}')
    print(f'{course}的最低分:{min(temp_scores)}')
    print(f'{course}成绩的方差:{variance(temp_scores)}')

notebook上下载某个库

! pip install…

!pip install -U…

# 查看库的版本
np.__version__
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = 'STZhongsong'
plt.rcParams['axes.unicode_minus'] = False
import random

names = ('Sam', 'Mary', 'Bob', 'Alex', 'Alice')
courses = ('语文', '数学', '英语')
scores = [[random.randrange(0, 101) for x in range(3)] for y in range(5)]
# array数组
scores = np.array(scores)
scores
type(scores) # numpy.ndarray
# 计算每个学生的平均分(沿着1轴求平均)
np.round(scores.mean(axis=1),1)
# 统计每门课的最高分(沿着0轴找最大)
scores.max(axis=0)
# 统计每门课的最低分(沿着0轴找最小)
scores.min(axis=0)
# 统计每门课的方差(沿着0轴求方差)
scores.var(axis=0)
# 创建DataFrame对象
df = pd.DataFrame(data=scores, colums=courses, index=names)
df
# 增加一个列(平均分)
df['平均分'] = np.round(df.mean(axis=1), 1)
df
%config InlineBackend.figure_format = 'svg'
# 生成柱状图
df.plot(kind='bar', y=['语文', '数学', '英语'])
plt.xticks(rotation=0)
plt.show()
# 增加一个行(方差)
df.loc['方差'] = df.var(axis=0)
df
# 写入excel
df.to_excel('学生成绩.xlsx')

三、Numpy的应用

# 通过array函数将List转换成ndarray
array1 = np.array([1, 2, 3, 4, 5], dtype='i8')
array1
type(array1)  # numpy.ndarray
# 元素个数
array1.size
# 维度
array1.ndim
# 形状
array1.shape
# 每个元素占用的内存空间(字节) 1个元素8个字节
array1.itemsize
# 元素的数据类型
array1.dtype
# 整个数组占用的内存空间(字节)
array1.nbytes
# 通过arange函数指定取值范围创建ndarray
array2 = np.arrange(1, 100, 2)
array2
# 通过linspace构造等差数列创建ndarray
array3 = np.linspace(-5, 5, 101)
%timeit list(range(1000000))
%timeit np.arange(1000000)
# 通过随机的方式创建ndarray对象
array4 = np.random.randint(60, 101, 15)
array4
# 创建10个0~1的小数
array5 = np.random.random(10)
array5
# 创建二维数组
array6 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
array6
array6[1][1] # 5
array6[2, 1] # 8
# 花式索引
array6[[0, 1, 1, 2], [2, 0, 2, 1]]   # array([3, 4, 6, 8])
# 布尔索引
array6[array6 > 5]   # array([6, 7, 8, 9])
array6[(array6 > 5) & (array6 % 2 == 0)]   # array([6, 8])
array6.ndim # 2
array6.shape # (3, 3)
# 用随机的方式创建二维数组
array7 = np.random.randint(60, 101, (5, 3))
array7
array8 = np.zeros((4, 5), dtype='i8')
array8
np.ones((2, 5), dtype='u8')
np.full((10, 10), 'ad')
array9 = np.eye(10)
array9
# 将一维数组调形成二维数组
array10 = array4.reshape((5,3))
array10
# 将二维数组调形成一维数组
array11 = array10.flatten()
array11
# 将数组变成列表
array11.tolist()

数组的索引和切片

array11[0] = 100
array11[[1, 3, 9]]
# 花式索引
array11[[1, 3, 9, -1, -1, 0, 0, 0]]
# 数组的关系运算会产生布尔数组
array11 >= 80
# 布尔索引
array11[array11 >= 80]
array11[(array11 % 2 != 0) & (array11 >= 80)]
array11[(array11 % 2 != 0) | (array11 >= 80)]
# 切片操作
array11[3:8]
array11[3:8:2]
array11[::-1]
array12=np.array([[0, 1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 7],[6, 7, 8, 9]])
array12
array12[0:2, 0:2]
array12[1:3, 1:3]
array12[2:, 2:]
array12[0::3, 0::3]
array13 = plt.imread('背景图.png')
array13
array13.ndim # 3
# 显示图片
plt.imshow(array13)
# 水平翻转
plt.imshow(array13[:, ::-1])
# 垂直翻转
plt.imshow(array13[::-1, :])
# 抠图
plt.imshow(array13[0:600, 1250::])
# 让图变模糊
plt.imshow(array13[::5,::5])
# 改颜色
plt.imshow(array13[::5, ::5, ::-1])

获取描述性统计信息

  1. 均值(mean):均值代表某个数据集的整体水平,我们经常提到的客单价、平均访问时长、平均配送时长等指标都是均值。均值的缺点是容易受极值的影响,虽然可以使用加权平均值来消除极值的影响,但是可能事先并不清楚数据的权重;对于正数可以用几何平均值来替代算术平均值。

    算术平均值:

x ˉ = 1 N ∑ i = 1 N x i \bar{x} = \frac {1} {N} \sum_{i=1}^{N}x_{i} xˉ=N1i=1Nxi

  1. 中位数(median):将数据按照升序或降序排列后位于中间的数,它描述了数据的中等水平。

  2. 众数:数据集合中出现频次最多的数据,它代表了数据的一般水平。数据的趋势越集中,众数的代表性就越好。众数不受极值的影响,但是无法保证唯一性和存在性。

  3. 最大值(max)/最小值(min),最大值减去最小值称为极差(peak-to-peak)。

  4. 方差(variance):将每个值与均值的偏差进行平方,然后除以总数据量得到的值。简单来说就是表示数据与期望值的偏离程度。方差越大,就意味着数据越不稳定、波动越剧烈,因此代表着数据整体比较分散,呈现出离散的趋势;而方差越小,意味着数据越稳定、波动越平滑,因此代表着数据整体比较集中。

    总体方差:

σ 2 = 1 N ∑ i = 1 N ( x i − μ ) 2 \sigma^2 = \frac {1} {N} \sum_{i=1}^{N} (x_i - \mu)^2 σ2=N1i=1N(xiμ)2

样本方差:

S 2 = 1 N − 1 ∑ i = 1 N ( x i − x ˉ ) 2 S^2 = \frac {1} {N-1} \sum_{i=1}^{N} (x_i - \bar{x})^2 S2=N11i=1N(xixˉ)2

  1. 标准差(standard deviation):将方差进行平方根运算后的结果,与方差一样都是表示数据与期望值的偏离程度。

    总体标准差:

σ = 1 N ∑ i = 1 N ( x i − μ ) 2 \sigma = \sqrt {\frac {1} {N} \sum_{i=1}^{N} (x_i - \mu)^2} σ=N1i=1N(xiμ)2

样本标准差:

S = 1 N − 1 ∑ i = 1 N ( x i − x ˉ ) 2 S = \sqrt {\frac {1} {N-1} \sum_{i=1}^{N} (x_i - \bar{x})^2} S=N11i=1N(xixˉ)2

  1. 四分位距离(inter-quartile-range):$ IQR = Q_3 - Q_1 $。

    • Q3:上四分位数(75%分位数)
    • Q1:下四分位数(25%分位数)
array14 = np.random.randint(20, 51, 10)
array14
array14.mean()
np.sort(array14) 注意:排序不改变原数组,而是产生新数组
np.median(array14)
array14.max()
array14.min()
array14.ptp()
array14.std()
array14.var()
# 下四分位数
q1 = np.quantile(array14, 0.25)
# 中位数 - 百分之五十分位数
q2 = np.quantile(array14, 0.5)
# 上四分位数
q3 = np.quantile(array14, 0.75)
print(q1, q2, q3)
# 四分位距离
q3 - q1

数组的其他方法

array15 = np.array([True, False, False])
array15
array15.all() # False
array15.any() # True
array14.astype(np.float64)
# 将数组对象以pickle协议进行序列化(把对象变成了bytes最后写到文件中)
# 存档
array14.dump('aaa')
# 读档
array16 = np.load('aaa', allow_pickle=True)
# 填充
array16.fill(50)
# 获取非零元素的索引
array17 = np.array([0, 1, 0, 2, 0, 0, 0, 3, 0])
array17[array17.nonzero()]
# 舍入
array18 = np.random.random(10) * 10
array18.round(2)
# 交换指定的轴
array13.swapaxes(0, 1).shape
plt.imshow(array13.swapaxes(0, 1)) # 图片变成竖着

给数组加元素

array3 = np.array([82, 36, 21, 23, 25, 43, 52, 59, 60, 76, 95])
# 给数组加元素
np.append(array3, 1000)
np.insert(array3, 0, 1000)
# 取元素
array3.take([0, 1, -2])
# 布尔索引
array3[array3 > 50]
array3[(array3 > 50) & (array3 % 2 == 0)]

数组与标量的运算

array4 = np.array([[1, 1, 1], [2, 3, 4], [5, 5, 6]])
array4 + 5
array4 * 5
5 * array4
array4 / 5
array4 ** 5
5 ** array4

数组与数组的运算

当两个数组形状不一致时,如果两个数组的后缘维度(shape属性从后往前看)相同或者其中一个的后缘维度为1,那么这个时候可以通过广播机制让两个数组的形状趋于一致,这种情况是可以进行运算的;如果不能应用广播机制,那么两个数组没有办法进行运算。

array5 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
array6 = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
array5 + array6
array5 ** array6
array7 = np.array([4, 4, 4])
array5 + array7
array8 = np.array([[4], [3], [2]])
array5 + array8
array9 = np.random.randint(1, 10, (4, 4))
array5 + array9
# ValueError: operands could not be broadcast together with shapes (3,3) (4,4)

numpy相关方法

# nan - not a number(空值)
array10 = np. array([1, 2, 3, np.nan, 4, np.inf])
np.isnan(array10) # 返回布尔值。是否为空值
# ~相当于not
array10[~np.isnan(array10)]
# isinf/isfinite 判断无穷大值
np.isinf(array10) # 返回布尔值
# 对数
array11 = np.array([1, 10, 100])
np.log10(array11)
# 画出正弦函数和余弦函数
x = np.linspace(-2 * np.pi, 2 * np.pi, 120)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x, y1, color='red', marker='x')
plt.plot(x, y2, color='green', marker='X')
# 画出对数
x = np.linspace(-2 * np.pi, 2 * np.pi, 120)
y1 = np.log(x)
y2 = np.log10(x)
plt.plot(x, y1, color='red', marker='x')
plt.plot(x, y2, color='black', marker='x')
a = np.array([0.1, 0.2, 0.3])
b = np.array([0.1, 0.2, 0.300001])
np.all(a == b) # False
np.allclose(a, b) # True
array11 = np.array([1, 4, 9])
array12 = np.array([2, 3, 5])
np.maximum(array11, array12) # array([2, 4, 9])
np.minimum(array11, array12) # array([1, 3, 5])

常用函数

array13 = np.array([12, 13, 12, 15, 20, 20, 17])
np.unique(array13) # array([12, 13, 15, 17, 20])
array6 = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
np.split(array6, 3, axis=1) # 沿着1轴切成三部分
array14 = np.arange(1, 10)
np.extract(array14 % 3 == 0, array14) # 提取3的倍数
# 小于3的数不变,大于5的数平方
np.select([array14 < 3, array14 > 5], [array14, array14 ** 2])

numpy对线性代数的支持
{ x 1 + 2 x 2 = 5 3 x 1 + 4 x 2 = 8 \begin{cases} x_1 + 2x_2 = 5 \\ 3x_1 + 4x_2 = 8 \end{cases} {x1+2x2=53x1+4x2=8

m1 = np.arange(1, 10).reshape((3, 3))
# 计算行列式的值
np.linalg.det(m1)
# 计算矩阵的秩
np.linalg.matrix_rank(m1)
m2 = np.arange(1, 5).reshape((2, 2))
b = np.array([5, 8]).reshape(-1, 1)
# 解线性方程组
np.linalg.solve(m2, b)
# 增广矩阵
np.hstack((m2, b))
# 判断两组数据相关性(皮尔逊系数)
x = np.arange(1, 11, dtype=np.float64)
y = np.array([10.14, 9.89, 8.41, 9.61, 7.95, 7.46, 6.62, 5.23, 4.70, 4.77])
# 越接近-1,负相关性越强,越接近1,正相关性越强
np.corrcoef(x, y)
# 绘制散点图
plt.scatter(x, y)
plt.xlabel('距离(km)')
plt.ylabel('单价(万元)')

四、Pandas的应用(重点)

创建Series对象

# data参数表示数据,index参数表示数据的索引(标签)
# 如果没有指定index属性,默认使用数字索引
ser1 = pd.Series(data=[320, 180, 300, 405, 130],  index=['一季度', '二季度', '三季度', '四季度','三季度'])
ser1
ser1[0]
ser1['一季度']
ser1['三季度']
# 通过字典创建Series对象,字典的key就是Series对象的索引
ser2 = pd.Series(data={
    '一季度':300,
    '二季度':180,
    '三季度':300,
    '四季度':405
})
ser2
# 切片
ser2[0:2] # 只取到第一季度,第二季度
# 切片
ser2['一季度':'三季度'] # 会取到第三季度
# 花式索引
ser2[['一季度', '三季度']]
# 布尔索引
ser2[ser2 >= 200]

Series对象的属性

# 获取Series对象的值(ndarray)
ser2.values
# 获取Series对象的索引(Index对象)
ser2.index
# 有没有空值
ser2.hasnans
# 是否单调
ser2.is_monotonic
# 是否每个元素都是唯一的
ser2.is_unique

Series对象的方法

# 获取描述性统计信息
ser2.describe()
ser2.describe()['25%']
ser2.describe()['max']
ser3 = pd.Series(['apple', 'banana', 'apple', 'pitaya', 'apple', 'pitaya', 'durian'])
# 获取独一无二的元素构成数组
ser3.unique()
# 去重
ser3.drop_duplicates()
# 不重复元素的个数
ser3.nunique()
# 判断是否重复,返回布尔值
ser3.duplicated()
# 统计频次
ser3.value_counts()
ser4 = pd.Series(data=[10, 20, np.NaN, 30, np.NaN])
# 判断空值
ser4.isnull()
# 判断非空值
ser4.notnull()
# 返回不是空值的值
ser4[ser4.notnull()]
# 删除空值
ser4.dropna()
# 填充空值
ser4.fillna(100)
# 用在中位数填充空值
ser4.fillna(ser4.median())
# 用前面的值填充后面的值
ser4.fillna(method='ffill')
# 用后面的值填充前面的值
ser4.fillna(method='bfill')
ser5 = pd.Series(np.arange(1, 10))
# 保留满足条件的数据,不满足的替换为指定值或置为空值
ser5.where(ser5 < 5, 99)
# 替换满足条件的值为指定值或置为空值
ser5.mask(ser5 < 5, 100)
ser6 = pd.Series(['cat', 'dog', np.nan, 'rabbit'])
# 基于字典进行数据映射,将cat,dog改为对应的值
ser6.map({'cat': 'kitten', 'dog': 'puppy'})
ser6.map('I am a {}'.format, na_action='ignore')
import math
ser7 = pd.Series(np.random.randint(30, 80, 50))
temp = ser7.apply(lambda x: math.floor(x ** 0.5 * 10))
# 成绩处理后的及格人数
temp[temp >= 60].count()
# 成绩处理前的及格人数
ser7[ser7 >= 60].count()
ser8 = pd.Series(data=[57, 96, 89, 35, 25, 12],index=['apple', 'banana', 'orange', 'grape', 'peach', 'pitaya'])
# 根据值排序
ser8.sort_values(ascending=False)
# 根据索引排序
ser8.sort_index(inplace=True)
import heapq

nums = [35, 12, 98, 57, 78, 42, 87]
heapq.nlargest(3, nums)
heapq.nsmallest(2, nums)
# 取最大的3个元素
ser8.nlargest(3)
# 取最小的2个元素
ser8.nsmallest(2)
ser9 = pd.Series({'一季度': 400, '二季度': 520, '三季度': 180, '四季度': 380})
# 画柱状图
ser9.plot(figsize=(6, 3), width=0.4, kind='bar', color=['r', 'y', 'b', 'g'])
plt.grid(True, alpha=0.25, axis='y', linestyle='--')
plt.xticks(rotation=0)
plt.yticks(np.arange(0, 601, 100))
for i in range(ser9.size):
    plt.text(i, ser9[i]+10, ser9[i], ha='center')
plt.show()
# 绘制饼图
ser9.plot(figsize=(6, 3), kind='pie', autopct='%.1f%%', wedgeprops=dict(width=0.4, edgecolor='white'), pctdistance=0.8)
plt.ylabel('')
plt.show()

创建DataFrame

# 通过二维数组或嵌套列表创建DataFrame对象
scores = np.random.randint(50, 101, (5, 3))
names = ('关羽', '张飞', '赵云', '马超', '黄忠')
courses = ('语文', '数学', '英语')
df1 = pd.DataFrame(data=scores, columns=courses, index=names)
df1
df1.info()
# 通过字典创建DataFrame对象
scores = {
    '语文': [62, 72, 93, 88, 93],
    '数学': [95, 65, 86, 66, 87],
    '英语': [66, 75, 82, 69, 82],
}
ids = [1001, 1002, 1003, 1004, 1005]
df2 = pd.DataFrame(data=scores, index=ids)
df2

读取csv文件

df3 = pd.read_csv(r'C:\Users\wby\Desktop\data\csv\2018年北京积分落户数据.csv', 
                  index_col='id',
                  # 包围内容的符号
                  quotechar='|',
                  usecols=['id', 'name', 'score'],
                  nrows=20,
                  skiprows=np.arange(1, 21)
)
df3
df4 = pd.read_csv(r'C:\Users\wby\Desktop\data\csv\bilibili.csv', encoding='gbk')
df4
df5 = pd.read_csv(r'C:\Users\wby\Desktop\data\csv\chipotle.tsv', delimiter='\t')
df5

读取excel文件

df6 = pd.read_excel(r'C:\Users\wby\Desktop\data\excel\2020年销售数据.xlsx', header=1,sheet_name='Sheet1',usecols=['销售日期', '销售区域', '销售渠道', '品牌','销售渠道'],nrows=100,skiprows=np.arange(2, 102))
df6
df7 = pd.read_excel(r'C:\Users\wby\Desktop\data\excel\阿里巴巴2020年股票数据.xlsx')
df7
df8 = pd.read_excel(r'C:\Users\wby\Desktop\data\excel\口罩销售数据.xlsx')
df8
df8 = pd.read_excel(r'C:\Users\wby\Desktop\data\excel\某视频网站运营数据.xlsx')
df8

读取MySQL数据库文件

!pip install pymysql
# 连接MySQL数据库创建DataFrame
import pymysql

conn = pymysql.connect(host='47.104.31.138', port=3306,
                     user='guest', password='Guest.618',
                      database='hrs', charset='utf8mb4')
conn
df9 = pd.read_sql('select dno, dname,  dloc from tb_dept', conn, index_col='dno')
df10 = pd.read_sql('select eno, ename, job, sal, comm, dno from tb_emp', conn, index_col='eno')
df10
df10['ename'].map(str.strip).apply(lambda x: x[0]+ '*' * (len(x)-1))
df10[['ename', 'sal']]
# 读某行数据
df10.loc[2056]
df10.iloc[1]
# 读三行数
df10.loc[[2056,7800, 3233]]
# 加一列数据,前面5人未婚,后面5人已婚
df10['married'] = ['未婚'] * 5 +['已婚'] * 9
# 加一行数据
df10.loc[9800]=['王博杨', '数据分析师', 2500, 250, 20, '未婚']
df10.loc[9900]={'ename': '呆鸡','job': '数据分析师', 'sal':1500, 'dno':20}
# 更改某个数据
df10.at[3088, 'job'] = 'java工程师'
# 拿某个数据
df10.iat[2, 1]
# 删掉两列数据
df10.drop(columns=['comm', 'married'])
# 删掉两行数据
# 删掉三行数据
df10.drop(index=[1359, 3233, 3088])
# 重置索引
df10.reset_index(inplace=True)
# 设置索引
df10.set_index('ename')
temp = df10.set_index(['dno', 'eno'])
# 重置为最开始的索引
temp.reset_index(level=0)
# 给索引改名字
df10.rename(columns={'eno': '编号', 'ename': '姓名'}, inplace=True)
# 调整索引的顺序
df10.reindex(columns=['编号', '姓名', 'sal', 'job', 'comm', 'dno', 'married'])
# inner join - 连接两张表
pd.merge(left=df10, right=df9, how='inner', on='dno')
df11 = pd.read_sql('select eno, ename, job, sal, comm, dno from tb_emp2', conn, index_col='eno')
df10 = pd.read_sql('select eno, ename, job, sal, comm, dno from tb_emp', conn, index_col='eno')
# union - 合并两张表的数据
pd.concat((df10, df11))
df10[df10.sal >= 4000]
df10[(df10.dno == 20) & (df10.sal >= 4000)]
df10.query('dno == 20 and sal >=4000')
import os

filenames = os.listdir(r'C:\Users\wby\Desktop\data\excel\xxx')
dfs =[pd.read_excel(os.path.join(r'C:\Users\wby\Desktop\data\excel\xxx', filename),header=1) for filename in filenames]
pd.concat(dfs,ignore_index=True).to_excel(r'C:\Users\wby\Desktop\data\excel\汇总数据.xlsx', index=False)

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