数据分析01


https://www.pypandas.cn/docs/user_guide/io.html

数值型描述统计(统计学)

算数平均值

$S = [s_1, s_2, ..., s_n] $

样本中的每个值都是真值与误差的和。

$mean = \frac{(s_1 + s_2 + ... + s_n) }{n}$

算数平均值表示对真值的无偏估计。

     
xxxxxxxxxx
       
m = np.mean(array)
m = array.mean()
m = df.mean(axis=0)
   

案例:针对电影评分数据做均值分析:

     
xxxxxxxxxx
       
mean = ratings['John Carson'].mean()
mean = np.mean(ratings['John Carson'])
means = ratings.mean(axis=1)
   

加权平均值

求平均值时,考虑不同样本的重要性,可以为不同的样本赋予不同的权重。

样本:$S = [s_1, s_2, s_3 ... s_n]$

权重:$W =[w_1, w_2, w_3 ... w_n]$

加权平均值:

 

代码实现:

     
xxxxxxxxxx
       
a = np.average(array, weights=volumes)
   

案例:自定义权重,求加权平均。

      ?x        
# 加权均值
w = np.array([3,1,1,1,1,1,1])
np.average(ratings.loc['Inception'], weights=w)
?
mask = ~pd.isna(ratings.loc['Inception']) 
np.average(ratings.loc['Inception'][mask], weights=w[mask])
   

最值

np.max() / np.min() / np.ptp(): 返回一个数组中最大值/最小值/极差(最大值减最小值)

     
xxxxxxxxxx
       
import numpy as np
# 产生9个介于[10, 100)区间的随机数
a = np.random.randint(10, 100, 9)
print(a)
print(np.max(a), np.min(a), np.ptp(a))
   

np.argmax() np.argmin(): 返回一个数组中最大/最小元素的下标

     
xxxxxxxxxx
       
print(np.argmax(a), np.argmin(a))
print(series.idxmax(), series.idxmin())
print(dataframe.idxmax(), dataframe.idxmin())
   

np.maximum() np.minimum(): 将两个同维数组中对应元素中最大/最小元素构成一个新的数组

     
xxxxxxxxxx
       
print(np.maximum(a, b), np.minimum(a, b), sep='\n')
   

中位数

将多个样本按照大小排序,取中间位置的元素。

若样本数量为奇数,中位数为最中间的元素

$[1, 2000, 3000, 4000, 10000000]$

若样本数量为偶数,中位数为最中间的两个元素的平均值

$[1,2000,3000,4000,5000,10000000]$

案例:分析中位数的算法,测试numpy提供的中位数API:

     
xxxxxxxxxx
       
import numpy as np
closing_prices = np.loadtxt('../../data/aapl.csv', 
delimiter=',', usecols=(6), unpack=True)
size = closing_prices.size
sorted_prices = np.msort(closing_prices)
median = (sorted_prices[int((size - 1) / 2)] + 
          sorted_prices[int(size / 2)]) / 2
print(median)
median = np.median(closing_prices)
print(median)
   

频数与众数

频数指一组数据中各离散值出现的次数,而众数则是指一组数据中出现次数最多的值。

     
xxxxxxxxxx
       
cars = np.array(['bmw', 'bmw', 'bz', 'audi', 'bz', 'bmw'])
cars = pd.Series(cars)
cars.value_counts()
cars.mode()
   

四分位数

所谓四分位数,即把数值由小到大排列并分成四等份,处于三个分割点位置的数值就是四分位数。

  • 第1四分位数 (Q1),又称“较小四分位数”,等于该样本中所有数值由小到大排列后第25%的数字。
  • 第2四分位数 (Q2),又称“中位数”,等于该样本中所有数值由小到大排列后第50%的数字。
  • 第3四分位数 (Q3),又称“较大四分位数”,等于该样本中所有数值由小到大排列后第75%的数字。

第3四分位数与第1四分位数的差距又称四分位距(InterQuartile Range,IQR)

     
xxxxxxxxxx
       
ary = np.array([1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,5,5,5])
s = pd.Series(ary)
s.quantile([.0, .25, .5, .75, 1.])
   

标准差

样本(sample):

 

平均值:

 

离差(deviation):表示某组数据距离某个中心点的偏离程度

 

离差方:

 

总体方差(variance):

 

总体标准差(standard deviation):

 

样本方差:

 

其中,n-1称之为“贝塞尔校正”,这是因为抽取样本时候,采集的样本主要是落在中心值附近,那么通过这些样本计算的方差会小于等于对总体数据集方差的无偏估计值。为了能弥补这方面的缺陷,那么我们把公式的n改为n-1,以此来提高方差的数值。称为贝塞尔校正系数。

样本标准差:

 

案例: 根据标准差理论,针对评分数据进行方差分析:

     
xxxxxxxxxx
       
ratings.std(axis=0)
   

宏观数值统计

     
xxxxxxxxxx
       
ratings.describe()
   

协方差、相关矩阵、相关系数

通过两组统计数据计算而得的协方差可以评估这两组统计数据的相似程度(相关性)。

样本

     
xxxxxxxxxx
       
A = [a1, a2, ..., an]
B = [b1, b2, ..., bn]
   

平均值

     
xxxxxxxxxx
       
ave_a = (a1 + a2 +...+ an)/n
ave_b = (b1 + b2 +...+ bn)/n
   

离差(用样本中的每一个元素减去平均数,求得数据的误差程度):

     
xxxxxxxxxx
       
dev_a = [a1, a2, ..., an] - ave_a
dev_b = [b1, b2, ..., bn] - ave_b
   

协方差

协方差可以简单反映两组统计样本的相关性,值为正,则为正相关;值为负,则为负相关,绝对值越大相关性越强。

     
xxxxxxxxxx
       
cov_ab = ave(dev_a x dev_b)
cov_ba = ave(dev_b x dev_a)
?
   

案例:计算两组股票数据的协方差,得出分析结论。

     
xxxxxxxxxx
       
bhp = pd.read_csv('../data/bhp.csv', header=None, usecols=[6], names=['closing'])
vale = pd.read_csv('../data/vale.csv', header=None, usecols=[6], names=['closing'])
?
#平均值
ave_bhp = np.mean(bhp)
ave_vale = np.mean(vale)
#离差
dev_bhp = bhp - ave_bhp
dev_vale = vale - ave_vale
#协方差
cov_ab = np.mean(dev_bhp*dev_vale)
cov_ab
   

相关系数

协方差除去两组统计样本标准差的乘积是一个[-1, 1]之间的数。该结果称为统计样本的相关系数。

     
xxxxxxxxxx
       
# a组样本 与 b组样本做对照后的相关系数
cov_ab/(std_a x std_b)
# b组样本 与 a组样本做对照后的相关系数
cov_ba/(std_b x std_a)
# a样本与a样本作对照   b样本与b样本做对照   二者必然相等
cov_ab/(std_a x std_b)=cov_ba/(std_b x std_a)
?
   

通过相关系数可以分析两组数据的相关性:

     
xxxxxxxxxx
       
若相关系数越接近于0,越表示两组样本越不相关。
若相关系数越接近于1,越表示两组样本正相关。
若相关系数越接近于-1,越表示两组样本负相关。
   

案例:输出案例中两组数据的相关系数。

     
xxxxxxxxxx
       
print('相关系数:', cov_ab/(np.std(a)*np.std(b)), cov_ba/(np.std(a)*np.std(b)))
   

相关矩阵

 

矩阵正对角线上的值都为1。(同组样本自己相比绝对正相关)

 

numpy与pandas提供了求得相关矩阵与协方差矩阵的API:

     
xxxxxxxxxx
       
# 相关矩阵
np.corrcoef(a, b)
dataFrame.corr()
?
# 协方差矩阵 
# [[aa的协方差,ab的协方差], [ba的协方差, bb的协方差]]
np.cov(a, b)
dataFrame.cov()
   

项目:保健品消费情况特征描述性统计分析

     
xxxxxxxxxx
       
...
...
...
...
   

apply函数

pandas提供了apply函数方便的处理Series与DataFrame;apply函数支持逐一处理数据集中的每个元素都会执行一次目标函数,把返回值存入结果集中。:

     
xxxxxxxxxx
       
# series.apply()
ary = np.array(['80公斤','83公斤','78公斤','74公斤','84公斤'])
s = pd.Series(ary)
def func(x):
    return x[:2]
s.apply(func)
?
# dataframe.apply()
def func(x):
    x[pd.isna(x)] = x.mean()
    return x
ratings.apply(func, axis=1)
   

排序

Pandas有两种排序方式,它们分别是按标签与按实际值排序。

     
xxxxxxxxxx
       
import numpy as np
?
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Minsu','Jack','Lee','David','Gasper','Betina','Andres']),
 'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
 'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])}
unsorted_df = pd.DataFrame(d)
   

按标签(行)排序

使用sort_index()方法,通过传递axis参数和排序顺序,可以对DataFrame进行排序。 默认情况下,按照升序对行标签进行排序。

     
xxxxxxxxxx
       
# 按照行标进行排序
sorted_df=unsorted_df.sort_index()
print (sorted_df)
# 控制排序顺序
sorted_df = unsorted_df.sort_index(ascending=False)
print (sorted_df)
   

按标签(列)排序

     
xxxxxxxxxx
       
# 按照列标签进行排序
sorted_df=unsorted_df.sort_index(axis=1)
print (sorted_df)
   

按某列值排序

像索引排序一样,sort_values()是按值排序的方法。它接受一个by参数,它将使用要与其排序值的DataFrame的列名称。

     
xxxxxxxxxx
       
sorted_df = unsorted_df.sort_values(by='Age')
print (sorted_df)
# 先按Age进行升序排序,然后按Rating降序排序
sorted_df = unsorted_df.sort_values(by=['Age', 'Rating'], ascending=[True, False])
print (sorted_df)
   

数据合并

concat

concat函数是在pandas的方法,可以根据不同的轴合并数据集。

     
xxxxxxxxxx
       
r = pd.concat(datas, axis=0, join='outer', ignore_index=False, 
              keys=['x', 'y', 'z'])
   

 

merge & join

panda具有全功能、高性能的内存连接操作,与SQL之类的关系数据库非常相似。与其他开源实现相比,这些方法的性能要好得多(在某些情况下要好一个数量级以上)

pandas提供了merge函数实现高效的内存链接操作:

     
xxxxxxxxxx
       
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,left_index=False, right_index=False)
   
参数名称说明
left 接收DataFrame或Series。表示要添加的新数据。无默认。
right 接收DataFrame或Series。表示要添加的新数据。无默认。。
how 接收inner,outer,left,right。表示数据的连接方式。默认为inner。
on 接收string或sequence。表示外键字段名。默认为None。
left_on 接收string或sequence。关联操作时左表中的关联字段名。
right_on 接收string或sequence。关联操作时右表中的关联字段名。
left_index 接收boolean。表示是否将left参数接收数据的index作为连接主键。默认为False。
right_index 接收boolean。表示是否将right参数接收数据的index作为连接主键。默认为False。
sort 接收boolean。表示是否根据连接键对合并后的数据进行排序。默认为False。
suffixes 接收接收tuple。表示用于追加到left和right参数接收数据重叠列名的尾缀默认为('x', 'y')。

合并两个DataFrame:

     
xxxxxxxxxx
       
import pandas as pd
left = pd.DataFrame({
         'student_id':[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
         'student_name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung', 'Billy', 'Brian', 'Bran', 'Bryce', 'Betty', 'Emma', 'Marry', 'Allen', 'Jean', 'Rose', 'David', 'Tom', 'Jack', 'Daniel', 'Andrew'],
         'class_id':[1,1,1,2,2,2,3,3,3,4,1,1,1,2,2,2,3,3,3,2], 
         'gender':['M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F'], 
         'age':[20,21,22,20,21,22,23,20,21,22,20,21,22,23,20,21,22,20,21,22], 
         'score':[98,74,67,38,65,29,32,34,85,64,52,38,26,89,68,46,32,78,79,87]})
right = pd.DataFrame(
         {'class_id':[1,2,3,5],
         'class_name': ['ClassA', 'ClassB', 'ClassC', 'ClassE']})
# 合并两个DataFrame
data = pd.merge(left,right)
print(data)
   

其他合并方法同数据库相同:

合并方法SQL等效描述
left LEFT OUTER JOIN 使用左侧对象的键
right RIGHT OUTER JOIN 使用右侧对象的键
outer FULL OUTER JOIN 使用键的联合
inner INNER JOIN 使用键的交集

实验:

     
xxxxxxxxxx
       
# 合并两个DataFrame (左连接)
rs = pd.merge(left,right,on='subject_id', how='right')
print(rs)
# 合并两个DataFrame (左连接)
rs = pd.merge(left,right,on='subject_id', how='outer')
print(rs)
# 合并两个DataFrame (左连接)
rs = pd.merge(left,right,on='subject_id', how='inner')
print(rs)
   

###