从零开始机器学习程序员我爱编程

从零开始机器学习-8 五分钟学会Pandas

2018-04-28  本文已影响241人  养薛定谔的猫

本文由 沈庆阳 所有,转载请与作者取得联系!

引言

在上一讲中,我们了解了机器学习程序中的数据集发挥着极为重要的作用。可以说,没有良好的数据集就无法得到合适的模型。但是准备数据集是一项极其枯燥乏味,且需要大量时间的工作。那么在学习和练习的过程中,有没有简单有效且迅速的方法来获取数据集呢?
答案是肯定的。现如今机器学习的社区日渐庞大,对于各种机器学习问题的数据集也越来越多。像我们前面提到的Microsoft维护的COCO数据集就是在目标检测上面的一个例子。对于一些数据格式来说,我们需要用数据分析的工具来讲现有的数据提取为我们需要的数据。对于列存数据的分析,我们使用Pandas API来进行。
Pandas是用于处理和分析输入数据的工具,目前很多机器学习的框架都支持使用Pandas数据结构作为输入。
安装Pandas很简单,通过pip install pandas命令即可完成对pandas的安装。
导入pandas,并输出相应的版本号。

import pandas as pd
pd.__version__

Pandas API的基本概念

创建Series和DataFrame对象

在进行如下学习的过程中,建议在Python Shell、或是Python控制台运行,因为可以直观地看到运行的结果,而不是需要print函数进行输出。
Pandas中的数据结构有如下两类:
1、DataFrame:由多个行和有名称的列构成的关系型数据表格。
2、Series:单一的列。每个Series均有一个名称,且一个DataFrame中包含一个或多个Series。
DataFrame是用于数据操控的一种常见的抽象实现形式。
通过如下代码可以创建Series:

pd.Series(['San Francisco', 'San Jose', 'Sacramento'])

控制台输出如下

0    San Francisco
1         San Jose
2       Sacramento
dtype: object

可以看到,我们定义了一列由CA的几个区名构成的一个Series(列)。
由一个或多个列组成一个DataFrame的例子如下:

city_names = pd.Series(['San Francisco', 'San Jose', 'Sacramento'])
population = pd.Series([852469, 1015785, 485199])

pd.DataFrame({ 'City name': city_names, 'Population': population })

首先,定义了city_names和population两个Series对象,并通过Pandas的DataFrame构造函数构造了一个新的DataFrame。在构造DataFrame的时候,为其每个Series指定了名称。
在DataFrame的构造函数中,其用法与Dictionary的用法较为类似。
在构造DataFrame的时候,如果两个Series的长度不一致,如一个Series有3行,一个Series有2行,那么构造的DataFrame较短的Series的第三行则为NA/Nan值来填充。
上述构建DataFrame的结果如下:

       City name  Population
0  San Francisco      852469
1       San Jose     1015785
2     Sacramento      485199
从网络读取数据与DataFrame的基本操作

大多数情况下,我们可以通过网络来读取数据,并创建特征定义。在Pandas中,可以使用pd.read_csv()函数来读取csv文件,并由此创建DataFrame对象。
以加利福尼亚的房价数据为例(california_housing_train.csv),文件存储位置(https://raw.githubusercontent.com/sqy941013/learnmachinelearning/master/california_housing_train.csv

california_housing_dataframe = pd.read_csv("https://raw.githubusercontent.com/sqy941013/learnmachinelearning/master/california_housing_train.csv", sep=",")
california_housing_dataframe.describe()

其通过pandas的DataFrame对象的describe()函数输出关于该的DataFrame的内容的一些统计信息如下:

          longitude      latitude  housing_median_age   total_rooms  \
count  17000.000000  17000.000000        17000.000000  17000.000000
mean    -119.562108     35.625225           28.589353   2643.664412
std        2.005166      2.137340           12.586937   2179.947071
min     -124.350000     32.540000            1.000000      2.000000
25%     -121.790000     33.930000           18.000000   1462.000000
50%     -118.490000     34.250000           29.000000   2127.000000
75%     -118.000000     37.720000           37.000000   3151.250000
max     -114.310000     41.950000           52.000000  37937.000000

       total_bedrooms    population    households  median_income  \
count    17000.000000  17000.000000  17000.000000   17000.000000
mean       539.410824   1429.573941    501.221941       3.883578
std        421.499452   1147.852959    384.520841       1.908157
min          1.000000      3.000000      1.000000       0.499900
25%        297.000000    790.000000    282.000000       2.566375
50%        434.000000   1167.000000    409.000000       3.544600
75%        648.250000   1721.000000    605.250000       4.767000
max       6445.000000  35682.000000   6082.000000      15.000100

       median_house_value
count        17000.000000
mean        207300.912353
std         115983.764387
min          14999.000000
25%         119400.000000
50%         180400.000000
75%         265000.000000
max         500001.000000

可以看到,我们的csv文件有经纬度、房屋年龄、总房间数等Series。而describe()函数统计了这些Series的总数(count)、平均数(mean)、最小值(min)等统计学中的信息。
与DataFrame有关的另一个比较有用的函数是head()。通过head()函数可以显示DataFrame的前几个记录

california_housing_dataframe.head()
   longitude  latitude  housing_median_age  total_rooms  total_bedrooms  \
0    -114.31     34.19                15.0       5612.0          1283.0
1    -114.47     34.40                19.0       7650.0          1901.0
2    -114.56     33.69                17.0        720.0           174.0
3    -114.57     33.64                14.0       1501.0           337.0
4    -114.57     33.57                20.0       1454.0           326.0

   population  households  median_income  median_house_value
0      1015.0       472.0         1.4936             66900.0
1      1129.0       463.0         1.8200             80100.0
2       333.0       117.0         1.6509             85700.0
3       515.0       226.0         3.1917             73400.0
4       624.0       262.0         1.9250             65500.0

此外,Pandas还可以绘制图表。例如DataFrame的Hist函数,我们可以快速地绘制出一个列中值的分布(需要安装matplotlib)。

california_housing_dataframe.hist('housing_median_age')

使用如下命令显示上图

from pylab import *
show()
Hist函数绘制的统计图
使用Pandas访问数据

访问Pandas的数据结构中的数据(DataFrame与Series)可以使用Python语言中访问Dictionary与List的语法来访问。
首先创建一个名为cities的DataFrame,然后输出cities中的city_names的所有数据:

cities = pd.DataFrame({ 'City name': city_names, 'Population': population })
print type(cities['City name'])
cities['City name']

运行结果:

<class 'pandas.core.series.Series'>
0    San Francisco
1         San Jose
2       Sacramento
Name: City name, dtype: object

或访问city_names的第2个数据:

print type(cities['City name'][1])
cities['City name'][1]

运行结果:

<type 'str'>
'San Jose'

或是输出第1到第2个数据:

print type(cities[0:2])
cities[0:2]

运行结果:

       City name  Population
0  San Francisco      852469
1       San Jose     1015785

关于Pandas的高级索引和选择功能,参见官方API文档:http://pandas.pydata.org/pandas-docs/stable/indexing.html

Pandas中操控数据

对Pandas中的数据结构的操作可以使用Python的基本运算指令。如:

population / 1000

得到:

0     852.469
1    1015.785
2     485.199
dtype: float64

还可以使用Numpy科学计算工具包进行计算,Pandas中的Series可以作为大部分Numpy函数的参数:
使用import numpy as np导入Numpy包。通过np.log(population)来进行控制台输出(以log函数为例)。

>>> import numpy as np
>>> np.log(population)
0    13.655892
1    13.831172
2    13.092314
dtype: float64

对于单列转换,可以使用Series.apply函数来进行。
与Python的映射函数类似,Series.apply()接收lambda函数,并且lambda函数运用于每个值。
以创建population是否超过100万的Series为例:

population.apply(lambda val: val > 1000000)
0    False
1     True
2    False
dtype: bool

从apply函数中,我们创建了一个新的Series,其存储的是population在该行是否人口大于100万。

对DataFrame的修改也很简单。我们可以对DataFrame进行添加新的Series。

>>> cities['Area square miles'] = pd.Series([46.87, 176.53, 97.92])
>>> cities['Population density'] = cities['Population'] / cities['Area square miles']
>>> cities
       City name  Population  Area square miles  Population density
0  San Francisco      852469              46.87        18187.945381
1       San Jose     1015785             176.53         5754.177760
2     Sacramento      485199              97.92         4955.055147
索引

Series和DataFrame也定义了index属性,其index属性会向每个Series或DataFrame行赋一个标识符。
初始情况下,构造Series或DataFrame时,Pandas会付给标识符反映原始数据顺序的索引值。一般来说,索引值在Series或DataFrame对象创建完成之后是稳定的。其不会根据数据的重新排序而发生改变。

>>> city_names.index
RangeIndex(start=0, stop=3, step=1)
>>> cities.index
RangeIndex(start=0, stop=3, step=1)

通过调用DataFrame的reindex()函数来进行各行的重新排序。

    City name   Population  Area square miles   Population density  Is wide and has saint name
2   Sacramento  485199  97.92   4955.055147 False
0   San Francisco   852469  46.87   18187.945381    False
1   San Jose    1015785 176.53  5754.177760 True

通过reindex()函数,我们可以对DataFrame进行打乱顺序重新排序(随机排序)。reindex()函数也可以和Numpy的random.permutation()函数相结合。

cities.reindex(np.random.permutation(cities.index))
    City name   Population  Area square miles   Population density  Is wide and has saint name
1   San Jose    1015785 176.53  5754.177760 True
2   Sacramento  485199  97.92   4955.055147 False
0   San Francisco   852469  46.87   18187.945381    False

参考文献:Google AI Study

觉得写的不错的朋友可以点一个 喜欢♥ ~
谢谢你的支持!

上一篇下一篇

猜你喜欢

热点阅读