R基础python家园我爱编程

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

2017-08-12  本文已影响0人  xuzhougeng

温故

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

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提供的相比效率相差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)
正态分布

)

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的异同(二):字符串操作 就介绍了两则的异同。

这些函数无法直接套用到ndarry, Series, DataFrame数据结构中,需要用到专门的方法。不过,pandas提供了矢量化的字符串方法,更加高效。

方法 说明
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)

最后结果如下:

结果示意
上一篇下一篇

猜你喜欢

热点阅读