在用Python进行数据处理的12个有用的Pandas技巧
原文链接:http://www.analyticsvidhya.com/blog/2016/01/12-pandas-techniques-python-data-manipulation/
本文由chinahadoop.com翻译
关于转载授授权
China Hadoop文章,欢迎个人转发朋友圈,自媒体、媒体、机构转载务必申请授权,后台留言“机构名称+文章标题+转载”,申请过授权的不必再次申请,只要按约定转载即可,但文末需放置China Hadoop二维码。
中国hadoop大数据峰会2016北京站3月18-19日在北京即将召开,现在购买门票优惠多多!!!机不可失,快快动起来!
Python正迅速成为数据科学家的首选语言-并且有很好的理由。它提供了一种程序设计语言以及良好科学计算库的深度的较大的生态系统。如果你打算开始学习Python语言,看看Python的学习路径。
在它的科学计算库,我发现Panda对于数据科学运算是最有用的。Panda以及Scikit-learn几乎提供了一个数据科学家所需要的全部知识。本文将侧重于提供用Python语言进行数据处理的12种方式。我也分享了一些能够让你工作更高效的提示和技巧。
我建议你在进行学习之前先看一下数据探索 的代码。为了帮助您更好地理解,我已经采取了数据集来展示这些操作和操纵。
数据集:我使用了贷款预测问题的数据集。下载数据集,并开始。
让我们开始吧
我将通过导入模块,并加载数据集到Python环境中来开始:
import pandas as pd
import numpy as np
data =pd.read_csv("train.csv", index_col="Loan_ID")
#1 – 布尔索引
如果你想以另一组列的条件来过滤列的值,你需要做什么?举例来说,我想要一张没有毕业并且获得贷款的女性名单列表。布尔索引在这里就能够帮上忙。你可以使用下面的代码:
data.loc[(data[“Gender”]==”Female”)& (data[“Education”]==”Not Graduate”) &(data[“Loan_Status”]==”Y”),[“Gender”,”Education”,”Loan_Status”]]
#2 – 应用功能
它是进行数据展示和创建新的变量常用的功能之一。应用传递数据帧的每个行/列的一些功能之后返回一些值。这些功能既可以是默认的或用户自定义的。例如,在这里它可以被用来找到每行和列中的#missing值。
#Create a newfunction:
def num_missing(x):
return sum(x.isnull())
#Applying percolumn:
print "Missingvalues per column:"
printdata.apply(num_missing, axis=0) #axis=0 defines that function is to be appliedon each column
#Applying per row:
print"\nMissing values per row:"
print data.apply(num_missing,axis=1).head() #axis=1 defines that function is to be applied on each row
因此,我们得到了期望的结果。
注:头()函数在第二输出使用,因为它包含许多行。
#3 – 填充缺失的文件
“fillna()'做它一气呵成。它使用列的整体平均值/模式/中值来更新缺失值。让我们把“性别”,“婚姻状况”和“雇佣情况”按照他们各自的模式放在不同的列。
#First we import afunction to determine the mode
from scipy.statsimport mode
mode(data[‘Gender’])
输出:ModeResult(mode=array([‘Male’], dtype=object), count=array([489]))
这同时返回模式和计数。记住该模式可以是数组,因为它有高频多值。我们将默认使用第一种:
mode(data[‘Gender’]).mode[0]
现在,我们可以填补缺失值,并检查使用技术#2。
#Impute the values:
data[‘Gender’].fillna(mode(data[‘Gender’]).mode[0],inplace=True)
data[‘Married’].fillna(mode(data[‘Married’]).mode[0],inplace=True)
data[‘Self_Employed’].fillna(mode(data[‘Self_Employed’]).mode[0],inplace=True)
#Now check the #missingvalues again to confirm:
printdata.apply(num_missing, axis=0)
因此,可以确认缺失值已经被补上了。请注意,这是归集的最原始的形式。其它尖端技术包括模拟补充缺失值、使用分组平均数(平均/模式/位)。我会在我的下一篇文章中讲述这一部分。
#4 – 透视表
Pandas可以用来创建MS Excel风格的透视表。例如,在下面这个例子中,一个关键列“LoanAmount”具有缺失值。我们可以使用每个“性别”,'婚姻状况'和'雇佣情况“组的平均量来估算它。各组的平均“LoanAmount'可被确定为:
#Determine pivottable
impute_grps = data.pivot_table(values=[“LoanAmount”],index=[“Gender”,”Married”,”Self_Employed”],aggfunc=np.mean)
print impute_grps
#5 – 多重索引
如果你注意步骤#3的输出,就会发现它有一个奇怪的特性。每个索引由3个值组成。这就是所谓的多重索引。它有助于快速执行操作。
继续#3示例,我们有每个组的值,但他们没有被输入。
这可以通过使用各种至今所学到的技术来完成这一步。
#iterate onlythrough rows with missing LoanAmount
for i,row in data.loc[data[‘LoanAmount’].isnull(),:].iterrows():
ind =tuple([row[‘Gender’],row[‘Married’],row[‘Self_Employed’]])
data.loc[i,’LoanAmount’] =impute_grps.loc[ind].values[0]
#Now check the#missing values again to confirm:
printdata.apply(num_missing, axis=0)
注意:
-
多指标需要定义在LOC语句指标组的数组。这就是一个用在函数中的数组。
-
该.values [0]需要后缀,因为在默认情况下返回了一系列元素,具有不与数据框匹配的索引。在这种情况下,直接分配给出了一个错误。
#6-交叉表
这个功能用来获取数据的初始“感觉”(图)。在这里,我们可以验证的一些基本假设。例如,在这种情况下,“Credit_History”有望显著影响贷款状态。这可以通过使用交叉列表进行试验,如下所示:
pd.crosstab(data[“Credit_History”],data[“Loan_Status”],margins=True)
这些都是绝对数字。但是,百分比在快速洞察中是更加直观的。我们可以通过应用函数做到这一点:
defpercConvert(ser):
return ser/float(ser[-1])
pd.crosstab(data[“Credit_History”],data[“Loan_Status”],margins=True).apply(percConvert,axis=1)
有信用记录的人中80%获得了贷款,没有信用记录的人中只有9%的人获得了贷款,通过这两个对比,所以显而易见的是有信用记录的人获得贷款的几率高于没有信用记录的人。
但是,并不是这样。有一个有趣的故事。因为我知道有信用记录是超级重要的,那么如果我预测那些有信用记录的人的贷款状态为Y和那些没有的为N会怎样呢。结果出人意料,我们刚好得到了460次,也就是614的75%。
如果你怀疑我们为什么需要统计模型,我不会怪你。但请相信我,提高超出这个标志0.001%的准确度都是一项艰巨的任务。你愿意参与这个挑战吗?
注: 75%是大概的数值。该测试仪会略有不同,但接近。另外,我希望这给一些想法,为什么精确度仅仅增长了0.05%,便可进入Kaggle的前500。
#7 – 合并DataFrames
当我们要整理来自不同来源的信息时,合并dataframes变得至关重要。假定一种情况,平均物业税(每平方米INR)可用于不同的属性类型。让我们定义一个dataframe为:
prop_rates =pd.DataFrame([1000, 5000, 12000],index=[‘Rural’,’Semiurban’,’Urban’],columns=[‘rates’])
prop_rates
现在,我们可以把原来的数据帧合并为这样的信息:
data_merged =data.merge(right=prop_rates,how='inner',left_on='Property_Area',right_index=True, sort=False)
data_merged.pivot_table(values='Credit_History',index=[‘Property_Area’,’rates’],aggfunc=len)
数据透视表验证成功的合并操作。请注意,“价值”的说法是不恰当的,因为在这里我们只是计数的值。
#8 – 排序DataFrames
Pandas允许基于多个列的简单排序。这个可以按照以下来做:
data_sorted =data.sort_values([‘ApplicantIncome’,’CoapplicantIncome’], ascending=False)
data_sorted[[‘ApplicantIncome’,’CoapplicantIncome’]].head(10)
注:Pandas的“sort”功能现在已经过时。我们应该用“sort_values”来代替。
#9 – 绘制(箱形图和柱状图)
你们中许多人可能不知道在Pandas中可以直接绘制箱形图和柱状图,并且分别调用matplotlib是没有必要的。这只是一个1行命令。例如,如果我们想通过Loan_Status来比较ApplicantIncome的分布:
importmatplotlib.pyplot as plt
%matplotlib inline
data.boxplot(column="ApplicantIncome",by="Loan_Status")
data.hist(column="ApplicantIncome",by="Loan_Status",bins=30)
这表明,收入不是一大决定因素,因为在谁收到贷款谁被拒绝了贷款这些人之间不存在明显的差异。
#10 – Cutfunction for binning
有时数值聚集在一起才更有意义。例如,如果我们试图模拟交通(#cars on road)的时间(minutes)模型。与每日实际的“早晨”“中午”“下午”“夜”“深夜”更替相比,一个小时的确切分钟对于预测流量可能不是相关。交通建模这种方式会更加直观,避免过度拟合。
在这里,我们定义一个简单的函数,它可以被重新用于相当容易地分箱的任何变量。
#Binning:
def binning(col,cut_points, labels=None):
#Define min and max values:
minval = col.min()
maxval = col.max()
#create list by adding min and max tocut_points
break_points = [minval] + cut_points +[maxval]
#if no labels provided, use default labels 0… (n-1)
if not labels:
labels = range(len(cut_points)+1)
#Binning using cut function of pandas
colBin= pd.cut(col,bins=break_points,labels=labels,include_lowest=True)
return colBin
#Binning age:
cut_points =[90,140,190]
labels =[“low”,”medium”,”high”,”very high”]
data[“LoanAmount_Bin”]= binning(data[“LoanAmount”], cut_points, labels)
print pd.value_counts(data[“LoanAmount_Bin”],sort=False)
#11 – Coding nominal data
通常情况下,我们发现,我们修改名义变量的类别的情况。这可能是由于各种原因:
-
有些算法(如Logistic回归)要求所有输入的是数字。所以名义变量大多编码为0,1 …(N-1)
-
有时一个类别可能以两种方式来表示。对于温度可能会被记录为“高”,“中”,“低”,“H”,“low”。这里, “高”和“H”是指同一类。同样地, “低”和“low”只有壳体的差异。不过,Python会把他们读为不同的层次。
-
某些类别可能有非常低的频率,把它们结合起来通常是一个好主意。
使用Pandas,我定义一个通用的函数,它接受输入的字典,并使用代码值“替换”功能。
#Define a generic functionusing Pandas replace function
def coding(col,codeDict):
colCoded = pd.Series(col, copy=True)
for key, value in codeDict.items():
colCoded.replace(key, value, inplace=True)
return colCoded
#Coding LoanStatusas Y=1, N=0:
print 'BeforeCoding:'
printpd.value_counts(data[“Loan_Status”])
data[“Loan_Status_Coded”]= coding(data[“Loan_Status”], {'N':0,'Y':1})
print '\nAfterCoding:'
printpd.value_counts(data[“Loan_Status_Coded”])
证明编码前后的类似计数。
#12 – 遍历 dataframe的所有行
这不是一个经常使用的操作。不过,你也不想被卡住。对吧?有时你可能需要使用for循环来遍历所有行。举例来说,我们面临着一个共同的问题是在Python中的变量不正确处理。这通常发生在:
-
将数字类别名义变量视为数值。
-
行中的一个输入的字符(由于数据错误)的数值变量被认为是明确的。
因此手动定义列类型通常是一个好主意。如果我们检查全部字段的数据类型:
#Check currenttype:
data.dtypes
在这里,我们看到Credit_History是一个名义变量,但显示为浮动。解决这些问题的一个好方法是创建有列名和类型的CSV文件。通过这种方式,我们可以做出一个通用的函数读取文件,然后指定列数据类型。举例来说,我在这里创建了一个CSV文件datatypes.csv。
#Load the file:
colTypes =pd.read_csv('datatypes.csv')
print colTypes
加载此文件后,我们可以通过各行迭代,并使用列“类型”中的“功能”列中定义的变量名来分配数据类型。
#Iterate througheach row and assign variable type.
#Note: astype isused to assign types
for i, row incolTypes.iterrows(): #i: dataframe index; row: each row in series format
if row[‘feature’]=="categorical":
data[row[‘feature’]]=data[row[‘feature’]].astype(np.object)
elif row[‘feature’]=="continuous":
data[row[‘feature’]]=data[row[‘feature’]].astype(np.float)
print data.dtypes
现在的信用记录栏被修改为用于Pandas代表名义变量“对象”类型。
结语
在这篇文章中,我们介绍了Pandas的各种功能,它可以使我们的生活更轻松,同时进行数据的探索和功能设计。此外,我们定义它可以在不同的数据集实现类似的目的被重复使用的一些通用功能。
China Hadoop大数据研究网:
http://chinahadoop.com/
中国hadoop技术峰会2016北京站报名参会网站:
http://www.chinahadoop.com/signup.php(也可点击阅读原文来了解详情)
门票价格表
微信名:
HadoopSummit
微信ID:
hadoopinchina
中国Hadoop技术峰会是亚太地区举办最早、规模最大、影响力最广阔的大数据盛会。
Chinahadoop.com是China Hadoop Summit的内容网站。
HadoopSummit是Chinahadoop.com的微信发布平台。