社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

像学R一样学Python(高级数据管理)

生信媛 • 7 年前 • 1086 次点击  

温故

在基本数据管理部分,主要是涉及到如何新建数据集,并且对数据集中的变量和观测值进行提取和操作。基本上用到了如下函数,可以根据函数名回忆一下用法:

import pandas as pd
import numpy as np
from pandas import Series, DataFrame
pd.read_table()
# 假设新建一个数据框为df
df.head(), df.tail(), df.shape(), df.dtypes()
df['var'] = values # 新建变量
np.where(), np.logical_and, np.less, np.greater # 变量重编码
df.index, df.columns, df.index.map, df.columns.map, df.index.rename, df.index.reanme # 变量重命名
df.isnull, df.notnull, df.dropna, df,fillna #  缺失值处理
pd.to_datetime# 日期值
df.astype # 数据类型转换
df.sorte_index df.sort.values # 排序
pd.merge, pd.concat, pd.appedn # 合并数据集
df.ix[], df[], df.loc[] # 数据取子集
df.sample # 抽样

知新,一个实际案例

这一次我们使用R语言实战高级数据管理的案例:

要讨论数值和字符处理函数,让我们首先考虑一个数据处理问题。一组学生参加了数学、科学和英语考试。为了给所有学生确定一个单一的成绩衡量指标,需要将这些科目的成绩组合起来。另外,你还想将前20%的学生评定为A,接下来20%的学生评定为B,依次类推。最后,你希望按字母顺序对学生排序。数据如表5-1所示。
观察此数据集,马上可以发现一些明显的障碍。首先,三科考试的成绩是无法比较的。由于它们的均值和标准差相去甚远,所以对它们求平均值是没有意义的。你在组合这些考试成绩之前,必须将其变换为可比较的单元。其次,为了评定等级,你需要一种方法来确定某个学生在前述得分上百分比排名。再次,表示姓名的字段只有一个,这让排序任务复杂化了。为了正确地将其排序,需要将姓和名拆开。

如下介绍的函数大部分在Python自带库如math,内置函数都有,但是都不是元素级别的,也就是必须要写一个显性的循环函数,和numpy,pandas提供的相比效率相差10~1000倍以上。

常用函数

数学函数


数学函数主要由numpy提供,避免用到Python的低效的内置循环,转而使用C封装高效的矢量化运算。用法都是np.func()

函数描述
abs, fabs绝对值。非复数值,用fabs
sqrt各元素的平方根
square计算各元素的平方
exp计算个元素的指数
log, log10, log2, log1p对数运算
sign计算各元素的正负号
ceil(x)不小于x的最小整数
floor(x)不大于x的最小整数
rint(x)将x四舍五入到最接近的整数,保留dtype
cos,  sin, tan余弦,正弦和正切
cosh, sinh,  tanh双曲余弦,双曲正弦和双曲正切
arccos, arcsin,  arctan反余弦,反正弦和反正切
arccosh, arcsinh,  arctanh反双曲余弦,反双曲正弦和反双曲正切

我们经常会用这些函数对数据进行变换。当然,你可能已经忘记了三角函数对应是什么图形了,这个时候就可以尝试一下自己作图了。

%matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
x = np.arange(-2*np.pi, 2*np.pi, 0.01*np.pi)
y = np.cos(x)
plt.plot(x,y)

更多有关的numpy的数学函数可以看官方文档的2.8.1节。


统计函数


pandas对象拥有一组常用的数学和统计方法,比如说最大值,最小值,均值,中位数,四分位数等。用法是df.func()。部分函数在numpy也有,因此是np.func

方法说明
desribe列计算汇总,列出四分位数等信息
max,min最大值和最小值
idxmin, idxmax最大值和最小值的索引位置
quantile分位数
sum求和
mean平均数
median中位数
mad根据平均值计算平均离差
var方差
std标准差
skew样本值的偏度(三阶矩)
kurt样本值的丰度(四阶矩)
cumsum样本的累积和
cummin,cummax累计最大值和最小值
cumprod累积积
diff计算一阶差分
pct_change计算百分比变化

简单案例:均值和标准差的计算

x = np.arange(1,10,1)
x.mean() # np.mean(x)
x.std() # np.std(x)

概率函数

根据定义,概率函数也属于统计类,但是pandas没有提供这类函数。这类函数用到一个专门的科学计算库 scipy, 是一组专门解决科学计算中各种标准问题域的包的集合。

为了能更好的应用,可能需要花一点功夫稍微讲解一下 scipy 的 概率函数(stats)模块。该模块提供了常用的概率分布,大致分为两类,连续型分布和离散型分布,这两类分布都是 rv__continuousrv_discrete 的子类。

比如说标准的正态函数分布,norm, 作为 rv_continuous的子类,它覆写了父类的pdf方法

norm.pdf(x) = exp(-x**2/2)/sqrt(2*pi)

用人类更加可读的形式写出来就是  也就是教科书上的定义方式。如果查看他的均值和方差,也是熟悉的0和1. 也就是说通过rv__continuousrv_discrete 这两个父类还能够构造出 stats 模块没有提供分布函数。

子类继承父类的方法,如 var, std, mean, median 提供分布的各统计量, expect 计算期望值, stats 函数提供了moments参数用于指定需要计算的统计量,m=mean, v=variance, s=Fisher’s skew, k=Fisher’s kurtosis.

R中的概率函数形如[dpqr] 分布函数英文缩写,scipy.stats则是分布函数英文缩写.方法

  • rvs(): 根据概率分布,返回随机数

  • pdf(x): 密度函数, 对应R的d

  • cdf(x): 给定随机变量(RV)的累积分布函数(),对应R的p

  • ppf(x): 分位数函数(quantile function) 对应R的q

  • sf(x): 生存函数(1-cdf)

常用的概率函数如下表

连续型分布缩写离散型分布缩写
Beta分布beta二项分布binorm
柯西分布cauchy几何分布geom
卡方分布chi2超几何分布hypergeom
指数分布expon负二项分布 nbinom
F分布f泊松分布poisson
(通用) Gmamma分布(gen)gamma--
对数正态分布exponnorm--
(通用)正态分布(gen)nrom)--

其他相关的分布用到的时候查官方文档就行了。

以熟悉的正态分布的有关函数和方法为例,了解这些函数的使用方法。如标准正态函数的密度函数(norm.pdf),分布函数(norm.ppf),随机数生成函数

绘制标准正态曲线

from scipy.stats import norm
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1)
x = np.linspace(-3,3,30) # 非常熟悉的MATLAB,对应R的pretty
y = norm.pdf(x) # 对应R的dnrom
ax.plot(x,y,'r-', lw=5, alpha=0.6, label='norm pdf')

norm.cdf(1.96)约等于0.975, norm.ppf(0.975) 与等于1.96。
norm.rvs(siez=(4,4))生成一个4X4的随机数,等同于np.random.normal(size=(4,4)).


字符处理函数


Python本身的字符处理模块是非常多的,比如说re用于正则,string是常用字符操作模块, 字符串数据类型本身还有许多方法。 我在简书上的一篇文章Python与R的异同(二):字符串操作,链接为http://www.jianshu.com/p/1cfe58e520e3  就介绍了两者的异同。

这些函数无法直接套用到ndarry, Series, DataFrame数据结构中,需要用到专门的方法。pandas提供了一些矢量化的文本操作方法,使用方式为df.str.methods


方法说明
len计算字符数量
contains是否符合含指定模式的布尔型数组
count最大值和最小值的索引位置
findall计算各字符串的模式列表
cat
实现元素级的字符串连接操作
get获取第i个元素
lower, upper大小写转换
match元素级别的re.match
split根据正则或指定分隔符进行分割
strip, rstrip, lstrip去除空白符,包括换行符

join

根据指定的分隔符进行连接
repeat对字符进行重复
replace用指定的字符串替换找到的模式

以《利用Python做数据分析》的数据为例,介绍如何匹配字符,提取指定内容。



data = {'Dava':'dave@google.com','Steve':'steve@gmail.com','Rob':'rob@gmail.com','Wes':np.nan}
data = Series(data)
data.str.contains('gmail')
import re
# 提取姓名等信息
pattern = re.compile(r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.[A-Z]{2,4}', flags=re.IGNORECASE)
data.str.findall(pattern)



将函数应用到Series和DataFrame中


我们介绍的数学函数和统计函数,大部分都是元素级别的操作,也就是能够直接应用到一系列数据结构上,包括Python自带的序列数据结构,list, tuple, numpy的ndarray,pandas提供的Series和DataFrame.

a = 5
np.sqrt(a) # 如果用math.sqrt(5),效率相差100倍
b = np.array([1.243,5.654,2.99])
np.round(b) # 比[round(x) for x in b] 快5倍
c = np.random.uniform(size=(3,4))
np.log(c)
np.mean(c)

默认情况下,np.mean计算的是总体均值,如果你希望按行按列计算均值的话,可以简单的使用np.meanc(c, axis=1),axis的0表示按列,1表示按行。还有一个比较通用的方法类似于R的apply函数。

numpy使用的apply_along_axisapply_over_axes;pandas则是为数据框提供了applyapplymap方法. 这里演示pandas的apply方法, 其他查看帮助文档就行。

# df.apply(func, axis=0), func可以是自定义函数
data = DataFrame(c)
data.apply(np.mean, 1)

除了apply外,pandas还允许用applymap映射原来的Python的自带函数成为元素级函数. 比如说直接用math.ceil(data)是不行的,需要用applymap进行映射。

data.applymap(lambda x : math.ceil(x)) #相比较np.ceil 效率相差80倍

解决问题

还记得之前提出的问题吗, 先回顾一下,然后用刚才学到的知识进行解决。

将学生的各科考试成绩组合为单一的成绩衡量指标、基于相对名次(前20%,下20%,等等)给出从A到F的评分、根据学生姓氏和名字的首字母对花名册进行排序

第一步: 数据输入

我是把成绩表格的数据输入到纯文本文件中,以逗号分隔,然后读取。

# 导入库
import numpy as np
from pandas import Series, Dataframe
# 数据
roster = pd.read_csv("student_grade.txt", header=None,names=["Student","Math","Science", "English"])

第二步: 计算综合评分。计算综合得分就是先对每一门学科的成绩进行标准化,然后进行相加。标准化的一种方法是归一化,即将一组数据进行均值为0,标准差为1的标准化。

score = np.mean(roster.ix[:,1:].apply(lambda x : (x-np.mean(x))/np.std(x)), axis=1)
roster['score'] = score

这一步比较复杂的就是我用了匿名函数进行标准化,然后用np.mean进行计算均值。

第三步: 计算四分位数, 并且学生进行评分

y = roster.score.quantile(q=[0.8,0.6,0.4,0.2])
grade = np.where(score > y.ix[0.8], 'A', np.where(score > y.ix[0.6], 'B', np.where(score > y.ix[0.4], 'D','F')))
roster['grade'] = grade

这一步用到了np.where进行元素级别的判断。、复制给grade列。

第四步: 根据学生姓氏和名字的首字母对花名册进行排序

first_name = roster.Student.apply(lambda x: x.split(sep=' ')[0])
last_name = roster.Student.apply(lambda x: x.split(sep=' ')[1])
roster['first_name'] = firt_name
roster['last_name'] = last_name
roster.drop('Student', axis=1, inplace=True)

同样用到了匿名函数, 对所有元素应用字符处理函数。

第五步: 排序




    
roster.sort_values(by=['first_name','last_name'], inplace=True)

最后结果如下:


系列文章

像学R一样学Python数据分析

下期预告

下次的内容是数据聚合和分组运算,对应的R语言实战的“整合和重构”,讲完该部分,后面就是具体的

欢迎小额打赏,支持我写作



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/z38Ad7ekwR
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/3037
 
1086 次点击