python数据分析

Numpy

概念

Numpy提供了两种基本的对象:ndarray(N-dimensional Array Object)和 ufunc(Universal Function Object)。ndarray是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。

数据类型
numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和C语言的数据类型对应上主要包括int8、int16、int32、int64、uint8、uint16、uint32、uint64、float16、float32、float64

numpy数组计算基础

numpy数组

数组的属性

ndarray(数组)是存储单一数据类型的多维数组。

属性 说明
ndim 返回 int。表示数组的维数
shape 返回 tuple。表示数组的尺寸,对于 n 行 m 列的矩阵,形状为(n,m)
size 返回 int。表示数组的元素总数,等于数组形状的乘积
dtype 返回 data-type。描述数组中元素的类型
itemsize 返回 int。表示数组的每个元素的大小(以字节为单位)。
数组的创建
numpy.array()
1
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
object 数组或嵌套的数列
dtype 数组元素的数据类型,可选
copy 对象是否需要复制,可选
order 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok 默认返回一个与基类类型一致的数组
ndmin 指定生成数组的最小维度
1
2
3
4
5
6
7
8
9
10
11
#使用array()创建数组默认是浮点型 (利用列表生成数组)
import numpy as np
a = np.array([1,2,3]) #创建一维数组
print (a) #输出结果[1 2 3]

a = np.array([[1, 2],[3, 4]]) #创建二维数组
print (a)
#输出结果
#[[1 2]
# [3 4]]

numpy.arange()
1
np.arange( start,stop,step,dtype)  #不含终值
参数 描述
start 起始值,默认为0
stop 终止值(不包含)
step 步长,默认为1
dtype 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。
numpy.linspace

numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:

1
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
参数 描述
start 序列的起始值
stop 序列的终止值,如果endpointtrue,该值包含于数列中
num 要生成的等步长的样本数量,默认为50
endpoint 该值为 true 时,数列中包含stop值,反之不包含,默认是True。
retstep 如果为 True 时,生成的数组中会显示间距,反之不显示。
dtype ndarray 的数据类型
numpy.logspace

numpy.logspace 函数用于创建一个于等比数列。格式如下:

1
np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)

base 参数意思是取对数的时候 log 的下标。

参数 描述
start 序列的起始值为:base ** start
stop 序列的终止值为:base ** stop。如果endpointtrue,该值包含于数列中
num 要生成的等步长的样本数量,默认为50
endpoint 该值为 true 时,数列中中包含stop值,反之不包含,默认是True。
base 对数 log 的底数。
dtype ndarray 的数据类型
img
生成随机数
img
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
#0到1标准正态分布
arr1 = np.random.randn(3, 3)
#0到1均匀分布
arr2 = np.random.rand(3, 3)
#均匀分布的随机数(浮点数),前两个参数表示随机数的范围,第三个表示生成随机数的个数
arr3 = np.random.uniform(0, 10, 2)
#均匀分布的随机数(整数),前两个参数表示随机数的范围,第三个表示生成随机数的个数
arr4 = np.random.randint(0, 10, 3)
print(f'arr1 : {arr1}\narr2 : {arr2}\narr3 : {arr3}\narr4 : {arr4}')
out :
# arr1 : [[-0.31637952 -0.08258995 1.43866984]
# [-0.11216775 0.43881134 0.11745847]
# [-1.1770306 -0.97657465 2.2368878 ]]
# arr2 : [[0.16350611 0.4467384 0.9465067 ]
# [0.1882318 0.40261184 0.93577701]
# [0.56243911 0.69179631 0.83407725]]
# arr3 : [4.41402883 6.03259052]
# arr4 : [9 7 7]
索引访问数组
一维数组索引

[start:stop:step]

多维数组索引

[行索引 , 列索引]

整数序列索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np 
#arr[1 , (0,2,3)] //索引第二行的,1,3,4列元素
x = np.array([[1, 2], [3, 4], [5, 6]])
y = x[[0,1,2], [0,1,0]]
print (y)

out:
#[1 4 5]

x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
rows = np.array( [ [0,0],[3,3] ] ) #表示第1、4行
cols = np.array( [ [0,2],[0,2] ] ) #表示第1、3列
y = x[rows,cols]
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
# out : array([[ 0, 2], [ 9, 11]])
布尔值索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np 

x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
print ('我们的数组是:')
print (x)
print ('\n')
# 现在我们会打印出大于 5 的元素
print ('大于 5 的元素是:')
print (x[x > 5])

out:
#我们的数组是:
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
#
#
# 大于 5 的元素是:
# [ 6 7 8 9 10 11]
变换数组形态

np.reshape(arr ,newshape, order=”c”)

展平数组

1
2
3
arr.ravel() 

arr.flatten('F') #有F纵向展平 无F横向展平

合并数组

1
2
3
4
5
np.hstack((arr1,arr2)) #横向合并

np.vstack((arr1,arr2)) #纵向合并

np.concatenate((arr1,arr2),axis=1) #axis=1横向 axis=0 纵向

分割数组

1
2
3
4
5
np.hsplit(arr,2) #横向分割数组

np.vsplit() #纵向分割数组

np.split(arr,2,axis= ) #0为纵向,1为横向

numpy矩阵

创建矩阵

1
2
3
4
5
matr1=np.mat("1 2 3; 4 5 6")

matr2=np.matrix([[1,2,3],[4,5,6]])

np.bmt('arr1,arr2;arr3,arr4') #合并成大矩阵

矩阵属性

1
2
3
4
mat.T #转置矩阵
mat.H #共轭转置矩阵
mat.I #逆矩阵
mat.A #二维数组

ufunc函数

通用函数,对数组中所有元素进行操作的函数。

ufunc的广播机制

不同形状数组之间执行算数运算的方式,ufunc会对形状相同的两个数组的对应元素进行计算,当两个数组形状不同时会实行广播机制

遵循4个原则

1.所有的输入数组向其中的shape最长的数组看齐,shape不足前面加1补齐

2.输出数组的shape是输入数组shape在各个轴上的最大值组合

3.两个数组的行或列要相同且其中一个数组的行或列为1

4.当输入数组的某个轴的长度为1时,使用此轴上的第一组值进行运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#广播机制
#当输入数组的某个轴的长度为1时,将使用此轴上的第一组值进行运算(即输入数组为一行或一列时,全用这一行或一列值进行运算)
arr1=np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
arr2=np.array([[1,2,3]])
print(arr1,arr2)
print(arr1+arr2)
print("-"*80)
arr3=np.array([[1,2,3,4]]).reshape(4,1)
print(arr3)
print(arr3+arr1)

#out:
[[0 0 0]
[1 1 1]
[2 2 2]
[3 3 3]] [[1 2 3]]

[[1 2 3]
[2 3 4]
[3 4 5]
[4 5 6]]
--------------------------------------------------------------------------------
[[1]
[2]
[3]
[4]]
[[1 1 1]
[3 3 3]
[5 5 5]
[7 7 7]]

numpy统计分析

读写文件

1
2
3
4
5
6
7
8
9
10
11
#二进制文件
np.save('保存路径/文件名',arr) #以二进制格式保存 文件.npy
np.savez('',arr1,arr2) #保存多个数组 文件.npz

data=np.load("文件") #读取多个 data['arr_0']

#文本文件
np.savetxt('路径',arr,fmt,delimiter) # fmt="%d" 保存时为整数 / delimiter="," 以逗号分隔
np.loadtxt()
np.genfromtxt()

利用函数进行简单统计分析

排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
arr.sort() #直接排序 axis=1 沿着横轴排序 axis=0 沿着纵轴排序
arr[::-1] #倒叙
arr.argsort() #返回值为排序后元素的索引位置
arr.lexsort(keys axis) # 多级排序 对最后一个key排序
a = np.random.randint(1, 100, size=5)
b = np.random.randint(1, 100, size=5)
c = np.random.randint(1, 100, size=5)
d = np.lexsort((a, b, c))
print(list(zip(a[d],b[d],c[d]))) #zip()函数返回一个zip对象,它是元组的迭代器,其中传递的每个迭代器中的第一个元素成对
print(d)
print(c[d])
print(a[d])

#out:
[20 32 75 56 84]
[60 92 74 97 50]
[54 74 9 53 31]
[(75, 74, 9), (84, 50, 31), (56, 97, 53), (20, 60, 54), (32, 92, 74)]
[2 4 3 0 1]
[ 9 31 53 54 74]
[75 84 56 20 32]
去重和重复
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#去重
np.unique(arr) #找出唯一值返回 =sorted(set(arr))
#重复
#tile
arr2=np.arange(5)
print(arr2,"\n",np.tile(arr2,3))
#out:
[0 1 2 3 4]
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4]

#repeat
arr3 = np.random.randint(1, 100, size=[3, 3])
print(arr3,"\n\n",arr3.repeat(2,axis=0))
#out:
[[80 15 93]
[59 75 23]
[ 4 92 72]]

[[80 15 93]
[80 15 93]
[59 75 23]
[59 75 23]
[ 4 92 72]
[ 4 92 72]]
常用统计函数
1
2
3
4
5
6
7
8
np.sum(arr,axis) #axis=1 横轴求和,=0纵轴求和 没有求总和
np.mean() #均值
np.std() #标准差
np.var() #方差
np.min() / max()
np.argmin() max() #最小/大 元素索引
np.cumsum() / cumprod() #累计和 / 累计积
item=data['item_id'].value_counts() #统计某一列中各个值的出现次数

Pandas统计分析

读写数据

1
2
3
4
pd.read_csv()
pd.read_excel()
dataframe.to_csv()
dataframe.to_excel()

读写数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pandas as pd
from sqlalchemy import create_engine

#连接数据库sqlalchemy
engine=create_engine('mysql+pymysql://root:lv513233@127.0.0.1:3306/a?charset=utf8')
print(engine)
#查看数据表清单
listdata=pd.read_sql_query('show tables',con=engine)
print(listdata)
#查看数据
news_data=pd.read_sql_table('news', con=engine)
print(news_data)

#写入数据
#to_sql('表名',con,if_exists)
#if_exists= fail 表名存在不写入/ replace 原表删除重写 / append 在原表上添加
news_data.to_sql('news_data',con=engine,if_exists='replace')

DataFrame

常用属性

1
2
dataframe.values,index,columns,dtypes
dataframe.size,ndim,shape,T

增删改查dataframe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#loc() / iloc() 访问
#df.loc[ 行名或条件,列名或条件 ]
#df.iloc[ 行索引,列索引 ]
df.loc[:,'A'] #提取A列所有
df.iloc[:,1] #提取第1列所有

df.loc[:,['A','B']] #提取A,B列所有
df.loc[2:6,['A','B']] #行名为2,3,4,5,6
df.loc[[1,3,5],['A','B']]
df.iloc[2:6,[1,3]] #2-5行

#条件切片
df.loc[df['A']=='a',['A','B']] # df数据中A列元素=a的 A列和B列
df.iloc[(df['A']=='a').value,[1,2]]

1
df.loc[df['A']=='a','A']=1 #将A列表=a的值改为1

1
2
#新增一列
df['新增列名']='值'

1
2
3
df.drop(labels,axis,inplace) #labels 表示要删除的列或行的索引 inplace 是否对原数据生效
df.drop(labels='A',axis=1,inplace=True) #删除A列
df.drop(labels=range(1:4),axis=0,inplace=True) #删除1-3行

描述性分析DataFrame数据

1
2
3
4
5
6
7
8
#数值型
df['A'].mean /describe()

#类别型
df['B'].value_counts()[:6] #对B列进行频数统计 前六行

#将数据类型改为Category
df['A'].astype('category')

转换处理时间序列数据

转化时间字符串为标准时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#转换Timestamp类
#unit 默认值为‘ns’,则将会精确到微妙,‘s'为秒
pd.to_datetime(df['A'],errors,dayfist/yearfirst) #将时间字符串转为Timestamp
data['timestamp'] = pd.to_datetime(data['timestamp'], unit='s')

#将时间转换为时间戳
data = data.apply(lambda x:time.mktime(x.timetuple()))
#x.timetuple()将时间转换为时间元组,提前导入time模块

#转换DatetimeIndex类 时间点
pd.DatetimeIndex()

#转换PeriodIndex类 时间段
pd.PeriodIndex() #freq="S" 指定时间间隔 Y(年) M D H T S(秒)

提取时间序列数据信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#Timestamp常用属性
#year week month quarter季节 date日期 time时间 weekofyear周数
# dayofyear一年中第几天 is_leap_year 是否是闰年
#[ 表达式 for 迭代变量 in 可迭代对象 [if条件表达式]] 实现对某一列时间信息的数据提取
data["year"]=[i.year for i in data["date"]]
data["month"]=[i.month for i in data["date"]]

# 将日期提取出来,这种方法提取出的日期需要进一步处理为datetime64格式
data['date'] = data['timestamp'].dt.date
data['date'] = pd.to_datetime(data['date'])
# 将时间取出来
data['time'] = data['timestamp'].dt.time
# 将小时提取出来
data['hour'] = data['timestamp'].dt.hour


#DatetimeIndex类,转换PeriodIndex类
dateIndex.weekday[:5]

加减时间数据

1
2
3
4
5
6
#Timedelta类
#加一天
time=data["date"]+pd.Timedelta["days=1"]

#与指定时间相减
time=data["date"]-pd.Timedelta['2024-1-1']

分组聚合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#groupby() 分组数据
#属性 count() 各组计数值 sum() mean() head()
#根据销售形势对数据分组
musicdataGroup=musicdata[['format','metric','value_actual']].groupby(by='format')


#聚合
#agg()
#使用agg()一次求出当前数据中所有销售数量,价格的总和和均值
data[['number_records','value_actual']].agg([np.sum,np.mean]

#apply()

#transfrom()

创建透视表和交叉表

pivot_table 创建透视表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pivot_table 创建透视表
#pivot_table(values,index,columns,aggfunc,margins,dropna)
#以format作为分组键创建的透视表 aggfunc 聚合函数
povot_data=pd.privot_table(data[['format','number_records','value_actual']],
index='format',aggfunc=np.sum)

#以format和metric作为分组键
povot_data=pd.privot_table(data[['format','metric','number_records','value_actual']],
index=['format','metric'],aggfunc=np.sum)

#以format为行分组键 metric作为列分组键
povot_data=pd.privot_table(data[['format','number_records','value_actual']],
index='format',columns='metric',aggfunc=np.sum)

#以format为行分组键 value_actual作为值
povot_data=pd.privot_table(data[['format','number_records','value_actual']],
index='format',values='value_actual',aggfunc=np.sum)

#透视表中缺失值进行填充 fill_value=0
povot_data=pd.privot_table(data[['format','number_records','value_actual']],
index='format',columns='metric',aggfunc=np.sum,fill_value=0)

#添加汇总数据 margins=True
povot_data=pd.privot_table(data[['format','number_records','value_actual']],
index='format',columns='metric',aggfunc=np.sum,fill_value=0,margins=True)

crosstab创建交叉表 计算分组频率

1
2
crosstab_data=pd.crosstab(index=data['format'],columns=data['metric'],
values=data['value_actual'],aggfunc=np.sum)

Pandas数据预处理

堆叠合并数据

1
2
3
4
5
6
7
8
9
10
11
12
#堆叠合并数据
#横向堆叠 concat()
# []列对象里面表示要合并的对象,
# axis 1为行对齐,0为列对齐,默认为0
# join (内连接 inner,交集)(outer外连接,并集)
#concat()可以进行纵向连接,表的列名一致
d1=pd.concat([df1,df2],axis=1,join="outer")
#concat()表列名不同时纵向合并结果
d2=pd.concat([df1,df2],axis=0,join="outer")
print(d1)
print(d2)
#纵向堆叠 append() 实现纵向堆叠的前提条件是表的列名完全一致 df1.append(df2)

主键合并数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#主键合并  merge()
data1=pd.read_csv("user_download.csv",encoding='gb18030')
data2=pd.read_csv("user_pay_info.csv")
# print(data1)
# print(data2)
#merge()
#how(连接方式,默认inner 内连接,outer外连接,left左连接,right右连接)
#left_on 要连接的左表的编号 right_on 要连接的右表的编号
data3=pd.merge(data1,data2,left_on="用户编号",right_on="编号")
print(data3)
#join() 连接的编号名要一样
#lsuffix 追加到左侧重叠列名的后缀
#rsuffix 追加到右侧重叠列名的后缀
#sort 对合并后的数据排序 默认为False
data2.rename(columns={'编号':'用户编号'},inplace=True)
download_pay1=data1.join(data2,on='用户编号',rsuffix='1')

清洗数据

去重

记录重复

1
2
3
4
5
6
7
#查看是否有重复值
print(data.duplicated().sum())
#drop_duplicates(subset,keep,inplace,ignore_index)
#keep 重复时保留第几个数据,first last False(不保留)
#subset 去重的列
df['A'].drop_duplicates()
df.drop_duplicates(subset['A','B'])

特征重复

去除连续的特征重复,利用特征间的相似度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#df.corr(method=) 默认pearson法 ,spearman,kendall
df[['A','B']].corr(method='kendall') #只能对数值型,类别特征无法计算

#df.equals(other)
#定义求取特征完全相同的矩阵的方法
d_euqlas=user_data["用户编号"].equals(user_data["编号"])

def feature_equals(df):
df_equals=pd.DataFrame([])
for i in df.columns:
for j in df.columns:
df_equals.loc[i,j]=df.loc[:,i].equals(df.loc[:,j])
return df_equals
app_desire=feature_equals(user_data)
print(app_desire.iloc[:7,:7])

#通过遍历的方式进行数据筛选出完全重复特征
len_feature=app_desire.shape[0]
dup_col=[]
for m in range(len_feature):
for n in range(m+1,len_feature):
if app_desire.iloc[m,n]&(app_desire.columns[n] not in dup_col):
dup_col.append(app_desire.columns[n])
print('需要删除的列',dup_col)

检测与处理缺失值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#检测
#isnull() / notnull()
df.isnull().sum() #每个特征缺失值数目

#处理
#删除缺失值 dropna(axis,how,thresh,subset,inplace)
#axis 0 删除记录 ,1 删除特征
#how any 只要有缺失值纯在就执行删除, all 全部为缺失值才删除
df.dropna(axis=0,how="any")

#替换 fillna()
#value 替换的值
#method 填补缺失值方式,bfill 使用下一个非缺失值来填补 ffill使用上一个
#用均值替换缺失值
mean_mun=df['A'].mean()
df['A']=df['A'].fillna(mean_num)


#插值法
#线性插值法 针对已知值求出线性方程,通过求解线性方程得到缺失值
from scipy.interpolate import interpld


#多项式插值 利用已知值拟合一个多项式
#拉格朗日插值 / 牛顿插值

#样条插值 每一个多项式由相邻的两个数据点决定

异常

Matplotlib可视化

seaborn