• Home
  • About
    • Brant photo

      Brant

      石纪 Brant Shi的个人博客.

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

三分钟对Pandas划重点

01 Sep 2019

Reading time ~3 minutes

Pandas简介

pandas 是一种列存数据分析 API。它是用于处理和分析输入数据的强大工具,很多机器学习框架都支持将 pandas 数据结构作为输入。 虽然全方位介绍 pandas API 会占据很长篇幅,但它的核心概念非常简单。本文将简要地对Pandas中的核心操作进行列举,介绍。

若欲对Pandas有更进一步,更全面的认识,可访问Pandas中文文档,其中包含了丰富的文档和教程资源。

以下通过一些引用进一步点明Pandas的地位和意味。

Pandas含有能使数据分析工作变得更快的高级数据结构和操作工具,Pandas是基于Numpy构建的,他让Numpy为中心的应用变得更简单了。

pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。

基本概念

通过以下标准方式导入pandas API及查询对应的API版本。

In[1]:  import pandas as pd
        pd.__version__
Out[1]: '0.24.2'

Pandas中的数据结构主要有以下两种:

  • DataFrame,您可以将它想象成一个关系型数据表格,其中包含多个行和已命名的列。
  • Series,它是单一列,类似于一维数组。DataFrame 中包含一个或多个 Series,每个 Series 均有一个名称。

Series

Series由两部分组成:数据和索引(标签),Series的字符串表现形式为索引在左,数据在右;索引可在创建series时给出或由Pandas自动创建一个由0开始递增的整数索引。

构建一个series对象的常见方法是由Series()方法传入一个列表:

In[2]:  s = pd.Series(['San Francisco', 'San Jose', 'Sacramento'])
        print(s)
Out[2]: 0    San Francisco
        1         San Jose
        2       Sacramento
        dtype: object

也可以在创建时按顺序给定索引值。

In[3]:  obj = Series(['a','b','c','d'],index = [9,2,3,4])
        print(obj)
Out[3]: 9    a
        2    b
        3    c
        4    d

可像数组的操作一样,通过索引来对Series中的元素进行查改;又因为索引可以自行定义(类似于dict,map),series可以看作是一个有序的dict,或是dict和list的结合体。

与此特点(有序dict)对应,series也可以通过传入一个dict创建:

In[4]:  obj = {'a':None,'b':678, 'c':139,'d':999}
        s = Series(obj)
        print(s)
Out[4]: a      NaN
        b    678.0
        c    139.0
        d    999.0

DataFrame

我们可以将映射 string 列名称的 dict 传递到它们各自的 Series,从而创建DataFrame对象。如果 Series 在长度上不一致,系统会用特殊的NA/NaN值填充缺失的值。例如:

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

        pd.DataFrame({ 'City name': city_names, 'Population': population })
Out[5]:     City name   Population
        0   San Francisco   852469
        1   San Jose    1015785
        2   Sacramento  485199

但是在大多数情况下,我们需要将整个文件(常为csv格式)加载到DataFrame中,如下所示:

In[6]:  california_housing_dataframe = pd.read_csv("https://download.mlcc.google.cn/mledu-datasets/california_housing_train.csv", sep=",")
        california_housing_dataframe.describe()
Out[6]:
    longitude   latitude    housing_median_age  total_rooms	total_bedrooms	population	households	median_income	median_house_value
count   17000.000000    17000.000000	17000.000000	17000.000000	17000.000000	17000.000000	17000.000000	17000.000000	17000.000000
mean    -119.562108	35.625225	28.589353	2643.664412	539.410824	1429.573941	501.221941	3.883578	207300.912353
std 2.005166    2.137340    12.586937	2179.947071	421.499452	1147.852959	384.520841	1.908157	115983.764387
min	-124.350000	32.540000	1.000000	2.000000	1.000000	3.000000	1.000000	0.499900	14999.000000
25%	-121.790000	33.930000	18.000000	1462.000000	297.000000	790.000000	282.000000	2.566375	119400.000000
50%	-118.490000	34.250000	29.000000	2127.000000	434.000000	1167.000000	409.000000	3.544600	180400.000000
75%	-118.000000	37.720000	37.000000	3151.250000	648.250000	1721.000000	605.250000	4.767000	265000.000000
max	-114.310000	41.950000	52.000000

上面的示例使用 DataFrame.describe 来显示关于 DataFrame 的统计信息。另一个实用函数是 DataFrame.head,它显示 DataFrame 的前n行数据(默认为全部),在此不再赘述。

pandas 的另一个强大功能是绘制图表。例如,借助 DataFrame.hist,您可以快速了解一个列中值的分布。

 In[7]:california_housing_dataframe.hist('housing_median_age')
 Out[7]: 见下图

DataFrame构造方式很多,下面给出可以输入到DataFrame构造器中的数据。

访问数据

我们可以使用熟悉的Python dict/list指令访问DataFrame数据

In[8]:  cities = pd.DataFrame({ 'City name': city_names, 'Population': population })
        print(type(cities['City name']))
        cities['City name']
Out[8]: <class 'pandas.core.series.Series'>

        0    San Francisco
        1         San Jose
        2       Sacramento
        Name: City name, dtype: object
In[9]:  print(type(cities['City name'][1]))
        cities['City name'][1]
Out[9]: <class 'str'>

        'San Jose'
In[9]:  print(type(cities[0:2]))
        cities[0:2]
Out[9]: <class 'pandas.core.frame.DataFrame'>

        City name   Population
    0   San Francisco   852469
    1   San Jose    1015785

除此之外,pandas针对高级索引和选择提供了极其丰富的API(数量过多,此处无法逐一列出)。

操控数据

我们也可以对Series应用Python的基本运算指令,例如:

In[10]:  population/1000.
Out[10]:    0     852.469
            1    1015.785
            2     485.199
            dtype: float64

由于Pandas是基于Numpy开发出的工具包,因而Pandas-Series可用作大多数Numpy函数的参数。对于更复杂的单列转换,可以使用 Series.apply。像 Python 映射函数一样,Series.apply 将以参数形式接受 lambda 函数,而该函数会应用于每个值。

下面的示例创建了一个指明 population 是否超过 100 万的新 Series

In[11]:  population.apply(lambda val: val > 1000000)
Out[11]:    0    False
            1     True
            2    False
            dtype: bool

而对DataFrame的修改方式也非常简单,与dict的操作类似。例如,以下列代码向现有的DataFrame添加了两个Series:

In[12]:  cities['Area square miles'] = pd.Series([46.87, 176.53, 97.92])
cities['Population density'] = cities['Population'] / cities['Area square miles']
cities
Out[12]:          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

索引-index

Series 和 DataFrame 对象也定义了 index 属性,该属性会向每个 Series 项或 DataFrame 行赋一个标识符值。

默认情况下,在构造时,pandas 会赋可反映源数据顺序的索引值。索引值在创建后是稳定的;也就是说,它们不会因为数据重新排序而发生改变。每个索引与对应行的数据是绑定的,类似于dict,即前文所讲series索引的特征。

In[13]: city.index
Out[13]:RangeIndex(start=0, stop=3, step=1)

可调用 DataFrame.reindex 以手动重新排列各行的顺序。例如,以下方式与按城市名称排序具有相同的效果:

In[14]: cities.reindex([2, 0, 1])
Out[14]:
           City name  Population  Area square miles  Population density
    2     Sacramento      485199              97.92         4955.055147  
    0  San Francisco      852469              46.87        18187.945381  
    1       San Jose     1015785             176.53         5754.17776

重建索引是一种随机排列 DataFrame 的绝佳方式。在下面的示例中,我们将取用类似数组的索引,然后将其传递至 NumPy 的 random.permutation 函数,该函数会随机排列其值的位置。如果使用此重新随机排列的数组调用 reindex,会导致 DataFrame 行以同样的方式随机排列。

In[15]: cities.reindex(np.random.permutation(cities.index))
Out[15]:
          City name  Population  Area square miles  Population density
    1       San Jose     1015785             176.53         5754.177760  
    2     Sacramento      485199              97.92         4955.055147  
    0  San Francisco      852469              46.87        18187.945381  

如果在使用 reindex 输入数组包含原始 DataFrame 索引值中没有的值,reindex 会为此类“丢失的”索引添加新行,并在所有对应列中填充 NaN 值:

In[16]: print(cities.reindex([0, 4, 5, 2]))
Out[16]:
               City name  Population  Area square miles  Population density
        0  San Francisco    852469.0              46.87        18187.945381  False
        4            NaN         NaN                NaN                 NaN    NaN
        5            NaN         NaN                NaN                 NaN    NaN
        2     Sacramento    485199.0              97.92         4955.055147

这种行为是可取的,因为索引通常是从实际数据中提取的字符串。 在这种情况下,如果允许出现“丢失的”索引,则可以轻松使用外部列表重建索引,因为不必担心会将输入清理掉。



Machine LearningPython Share Tweet +1