Python Pandas 快速指南



Python Pandas - 简介

Pandas 是一个开源的 Python 库,它使用强大的数据结构提供高性能的数据操作和分析工具。Pandas 的名称来源于面板数据——计量经济学中的多维数据。

2008 年,开发者 Wes McKinney 在需要一个高性能、灵活的工具来分析数据时开始开发 pandas。

在 Pandas 之前,Python 主要用于数据清洗和准备。它对数据分析的贡献非常小。Pandas解决了这个问题。使用 Pandas,我们可以完成数据处理和分析中的五个典型步骤,无论数据来源如何——加载、准备、操作、建模和分析。

Python 与 Pandas 广泛应用于包括金融、经济学、统计学、分析学等在内的学术和商业领域。

Pandas 的关键特性

  • 快速高效的 DataFrame 对象,具有默认和自定义索引。
  • 用于将数据从不同文件格式加载到内存中数据对象的工具。
  • 数据对齐和缺失数据的集成处理。
  • 数据集的重塑和透视。
  • 基于标签的大型数据集的切片、索引和子集选择。
  • 可以删除或插入数据结构中的列。
  • 对数据进行分组以进行聚合和转换。
  • 高性能的数据合并和连接。
  • 时间序列功能。

Python Pandas - 环境设置

标准 Python 发行版不包含 Pandas 模块。一个轻量级的替代方案是使用流行的 Python 包安装程序 **pip** 安装 NumPy。

pip install pandas

如果您安装 Anaconda Python 包,Pandas 将默认安装如下:

Windows

Linux

各个 Linux 发行版的包管理器用于安装 SciPy 栈中的一个或多个包。

对于 Ubuntu 用户

sudo apt-get install python-numpy python-scipy python-matplotlibipythonipythonnotebook
python-pandas python-sympy python-nose

对于 Fedora 用户

sudo yum install numpyscipy python-matplotlibipython python-pandas sympy
python-nose atlas-devel

数据结构介绍

Pandas 处理以下三种数据结构:

  • Series
  • DataFrame
  • Panel

这些数据结构构建在 Numpy 数组之上,这意味着它们速度很快。

维度和描述

理解这些数据结构的最佳方法是,更高维的数据结构是其低维数据结构的容器。例如,DataFrame 是 Series 的容器,Panel 是 DataFrame 的容器。

数据结构 维度 描述
Series 1 一维带标签的同质数组,大小不可变。
DataFrame 2 一般的二维带标签的、大小可变的表格结构,可能包含异构类型的列。
Panel 3 一般的三维带标签的、大小可变的数组。

构建和处理两个或多个维度的数组是一项繁琐的任务,用户需要在编写函数时考虑数据集的方向。但是使用 Pandas 数据结构,可以减少用户的脑力负担。

例如,对于表格数据 (DataFrame),从语义上讲,考虑 **索引**(行)和 **列** 比考虑轴 0 和轴 1更有帮助。

可变性

所有 Pandas 数据结构的值都是可变的(可以更改),除了 Series 之外,所有数据结构的大小都是可变的。Series 的大小是不可变的。

**注意** - DataFrame 广泛使用,并且是最重要的数据结构之一。Panel 的使用要少得多。

Series

Series 是一种一维类似数组的结构,包含同质数据。例如,以下 Series 是整数 10、23、56……的集合。

10 23 56 17 52 61 73 90 26 72

关键点

  • 同质数据
  • 大小不可变
  • 数据值可变

DataFrame

DataFrame 是一个二维数组,包含异构数据。例如:

姓名 年龄 性别 评分
Steve 32 3.45
Lia 28 4.6
Vin 45 3.9
Katie 38 2.78

该表显示了一个组织销售团队的数据及其整体绩效评分。数据以行和列表示。每一列代表一个属性,每一行代表一个人。

列的数据类型

四列的数据类型如下:

类型
姓名字符串
年龄整数
性别字符串
评分浮点数

关键点

  • 异构数据
  • 大小可变
  • 数据可变

Panel

Panel 是一种三维数据结构,包含异构数据。很难用图形表示来表示 Panel。但是,Panel 可以被说明为 DataFrame 的容器。

关键点

  • 异构数据
  • 大小可变
  • 数据可变

Python Pandas - Series

Series 是一种一维带标签的数组,能够保存任何类型的数据(整数、字符串、浮点数、Python 对象等)。轴标签统称为索引。

pandas.Series

可以使用以下构造函数创建 pandas Series:

pandas.Series( data, index, dtype, copy)

构造函数的参数如下:

序号 参数和描述
1

data

data 可以采用各种形式,例如 ndarray、列表、常量

2

index

索引值必须唯一且可哈希,与 data 长度相同。如果没有传递索引,则默认为 **np.arange(n)**。

3

dtype

dtype 用于数据类型。如果为 None,则将推断数据类型

4

copy

复制数据。默认为 False

可以使用各种输入创建 Series,例如:

  • 数组
  • 字典
  • 标量值或常量

创建空 Series

可以创建的基本 Series 是空 Series。

示例

#import the pandas library and aliasing as pd
import pandas as pd
s = pd.Series()
print s

其 **输出** 如下:

Series([], dtype: float64)

从 ndarray 创建 Series

如果 data 是一个 ndarray,则传递的 index 必须具有相同的长度。如果没有传递 index,则默认情况下 index 将为 **range(n)**,其中 **n** 是数组长度,即 [0,1,2,3…. **range(len(array))-1]。**

示例 1

#import the pandas library and aliasing as pd
import pandas as pd
import numpy as np
data = np.array(['a','b','c','d'])
s = pd.Series(data)
print s

其 **输出** 如下:

0   a
1   b
2   c
3   d
dtype: object

我们没有传递任何 index,因此默认情况下,它分配了从 0 到 **len(data)-1** 的索引,即 0 到 3。

示例 2

#import the pandas library and aliasing as pd
import pandas as pd
import numpy as np
data = np.array(['a','b','c','d'])
s = pd.Series(data,index=[100,101,102,103])
print s

其 **输出** 如下:

100  a
101  b
102  c
103  d
dtype: object

我们在这里传递了 index 值。现在我们可以在输出中看到自定义的索引值。

从字典创建 Series

可以将 **字典** 作为输入传递,如果未指定 index,则字典键将按排序顺序排列以构建 index。如果传递了 **index**,则将提取与 index 中标签对应的 data 中的值。

示例 1

#import the pandas library and aliasing as pd
import pandas as pd
import numpy as np
data = {'a' : 0., 'b' : 1., 'c' : 2.}
s = pd.Series(data)
print s

其 **输出** 如下:

a 0.0
b 1.0
c 2.0
dtype: float64

**注意** - 字典键用于构建索引。

示例 2

#import the pandas library and aliasing as pd
import pandas as pd
import numpy as np
data = {'a' : 0., 'b' : 1., 'c' : 2.}
s = pd.Series(data,index=['b','c','d','a'])
print s

其 **输出** 如下:

b 1.0
c 2.0
d NaN
a 0.0
dtype: float64

**注意** - 保留索引顺序,缺失元素用 NaN(非数字)填充。

从标量创建 Series

如果 data 是一个标量值,则必须提供 index。该值将重复以匹配 **index** 的长度

#import the pandas library and aliasing as pd
import pandas as pd
import numpy as np
s = pd.Series(5, index=[0, 1, 2, 3])
print s

其 **输出** 如下:

0  5
1  5
2  5
3  5
dtype: int64

使用位置从 Series 访问数据

序列中的数据可以像访问ndarray一样访问。

示例 1

检索第一个元素。我们已经知道,数组的计数从零开始,这意味着第一个元素存储在第零个位置,以此类推。

import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])

#retrieve the first element
print s[0]

其 **输出** 如下:

1

示例 2

检索序列中的前三个元素。如果在前面插入一个:,则将提取从该索引开始的所有项。如果使用两个参数(它们之间用:隔开),则提取这两个索引之间的项(不包括停止索引)。

import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])

#retrieve the first three element
print s[:3]

其 **输出** 如下:

a  1
b  2
c  3
dtype: int64

示例3

检索最后三个元素。

import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])

#retrieve the last three element
print s[-3:]

其 **输出** 如下:

c  3
d  4
e  5
dtype: int64

使用标签(索引)检索数据

Series类似于固定大小的dict,您可以通过索引标签获取和设置值。

示例 1

使用索引标签值检索单个元素。

import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])

#retrieve a single element
print s['a']

其 **输出** 如下:

1

示例 2

使用索引标签值的列表检索多个元素。

import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])

#retrieve multiple elements
print s[['a','c','d']]

其 **输出** 如下:

a  1
c  3
d  4
dtype: int64

示例3

如果标签不存在,则会引发异常。

import pandas as pd
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])

#retrieve multiple elements
print s['f']

其 **输出** 如下:

…
KeyError: 'f'

Python Pandas - DataFrame

DataFrame是一个二维数据结构,即数据以表格形式在行和列中对齐。

DataFrame的特征

  • 列的类型可能不同
  • 大小——可变
  • 带标签的轴(行和列)
  • 可以对行和列执行算术运算

结构

让我们假设我们正在创建一个包含学生数据的数据框。

Structure Table

您可以将其视为SQL表或电子表格数据表示。

pandas.DataFrame

可以使用以下构造函数创建pandas DataFrame:

pandas.DataFrame( data, index, columns, dtype, copy)

构造函数的参数如下:

序号 参数和描述
1

data

data采用多种形式,例如ndarray、series、map、列表、dict、常量以及另一个DataFrame。

2

index

对于行标签,用于结果框架的索引是可选的,如果没有传递索引,则默认为np.arange(n)。

3

对于列标签,可选的默认语法是- np.arange(n)。只有在没有传递索引的情况下才为真。

4

dtype

每列的数据类型。

5

copy

此命令(或任何它是什么)用于复制数据,如果默认值为False。

创建DataFrame

可以使用各种输入创建pandas DataFrame,例如:

  • 列表
  • 字典
  • Series
  • NumPy ndarrays
  • 另一个DataFrame

在本章的后续部分,我们将看到如何使用这些输入创建DataFrame。

创建空DataFrame

可以创建的基本DataFrame是一个空DataFrame。

示例

#import the pandas library and aliasing as pd
import pandas as pd
df = pd.DataFrame()
print df

其 **输出** 如下:

Empty DataFrame
Columns: []
Index: []

从列表创建DataFrame

可以使用单个列表或列表的列表创建DataFrame。

示例 1

import pandas as pd
data = [1,2,3,4,5]
df = pd.DataFrame(data)
print df

其 **输出** 如下:

     0
0    1
1    2
2    3
3    4
4    5

示例 2

import pandas as pd
data = [['Alex',10],['Bob',12],['Clarke',13]]
df = pd.DataFrame(data,columns=['Name','Age'])
print df

其 **输出** 如下:

      Name      Age
0     Alex      10
1     Bob       12
2     Clarke    13

示例3

import pandas as pd
data = [['Alex',10],['Bob',12],['Clarke',13]]
df = pd.DataFrame(data,columns=['Name','Age'],dtype=float)
print df

其 **输出** 如下:

      Name     Age
0     Alex     10.0
1     Bob      12.0
2     Clarke   13.0

注意——观察,dtype参数将“年龄”列的类型更改为浮点型。

从ndarray/列表的字典创建DataFrame

所有ndarrays的长度必须相同。如果传递了索引,则索引的长度应等于数组的长度。

如果没有传递索引,则默认情况下,索引将为range(n),其中n为数组长度。

示例 1

import pandas as pd
data = {'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}
df = pd.DataFrame(data)
print df

其 **输出** 如下:

      Age      Name
0     28        Tom
1     34       Jack
2     29      Steve
3     42      Ricky

注意——观察值0,1,2,3。它们是使用函数range(n)为每个值分配的默认索引。

示例 2

现在让我们使用数组创建一个带索引的DataFrame。

import pandas as pd
data = {'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}
df = pd.DataFrame(data, index=['rank1','rank2','rank3','rank4'])
print df

其 **输出** 如下:

         Age    Name
rank1    28      Tom
rank2    34     Jack
rank3    29    Steve
rank4    42    Ricky

注意——观察,index参数为每一行分配一个索引。

从字典列表创建DataFrame

字典列表可以作为输入数据传递来创建DataFrame。字典键默认作为列名。

示例 1

以下示例演示如何通过传递字典列表来创建DataFrame。

import pandas as pd
data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
df = pd.DataFrame(data)
print df

其 **输出** 如下:

    a    b      c
0   1   2     NaN
1   5   10   20.0

注意——观察,NaN(非数字)附加在缺失区域。

示例 2

以下示例演示如何通过传递字典列表和行索引来创建DataFrame。

import pandas as pd
data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
df = pd.DataFrame(data, index=['first', 'second'])
print df

其 **输出** 如下:

        a   b       c
first   1   2     NaN
second  5   10   20.0

示例3

以下示例演示如何使用字典列表、行索引和列索引创建DataFrame。

import pandas as pd
data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]

#With two column indices, values same as dictionary keys
df1 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b'])

#With two column indices with one index with other name
df2 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b1'])
print df1
print df2

其 **输出** 如下:

#df1 output
         a  b
first    1  2
second   5  10

#df2 output
         a  b1
first    1  NaN
second   5  NaN

注意——观察,df2 DataFrame是用字典键以外的列索引创建的;因此,在适当的位置附加了NaN。而df1是用与字典键相同的列索引创建的,因此附加了NaN。

从Series的字典创建DataFrame

可以传递Series的字典来形成DataFrame。结果索引是传递的所有Series索引的并集。

示例

import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print df

其 **输出** 如下:

      one    two
a     1.0    1
b     2.0    2
c     3.0    3
d     NaN    4

注意——观察,对于series one,没有传递标签‘d’,但在结果中,对于d标签,附加了NaN。

现在让我们通过示例了解列选择、添加删除

列选择

我们将通过从DataFrame中选择一列来理解这一点。

示例

import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print df ['one']

其 **输出** 如下:

a     1.0
b     2.0
c     3.0
d     NaN
Name: one, dtype: float64

列添加

我们将通过向现有数据框添加新列来理解这一点。

示例

import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)

# Adding a new column to an existing DataFrame object with column label by passing new series

print ("Adding a new column by passing as Series:")
df['three']=pd.Series([10,20,30],index=['a','b','c'])
print df

print ("Adding a new column using the existing columns in DataFrame:")
df['four']=df['one']+df['three']

print df

其 **输出** 如下:

Adding a new column by passing as Series:
     one   two   three
a    1.0    1    10.0
b    2.0    2    20.0
c    3.0    3    30.0
d    NaN    4    NaN

Adding a new column using the existing columns in DataFrame:
      one   two   three    four
a     1.0    1    10.0     11.0
b     2.0    2    20.0     22.0
c     3.0    3    30.0     33.0
d     NaN    4     NaN     NaN

列删除

列可以被删除或弹出;让我们举个例子来理解如何操作。

示例

# Using the previous DataFrame, we will delete a column
# using del function
import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']), 
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']), 
   'three' : pd.Series([10,20,30], index=['a','b','c'])}

df = pd.DataFrame(d)
print ("Our dataframe is:")
print df

# using del function
print ("Deleting the first column using DEL function:")
del df['one']
print df

# using pop function
print ("Deleting another column using POP function:")
df.pop('two')
print df

其 **输出** 如下:

Our dataframe is:
      one   three  two
a     1.0    10.0   1
b     2.0    20.0   2
c     3.0    30.0   3
d     NaN     NaN   4

Deleting the first column using DEL function:
      three    two
a     10.0     1
b     20.0     2
c     30.0     3
d     NaN      4

Deleting another column using POP function:
   three
a  10.0
b  20.0
c  30.0
d  NaN

行选择、添加和删除

我们现在将通过示例了解行选择、添加和删除。让我们从选择的概念开始。

按标签选择

可以通过将行标签传递给loc函数来选择行。

import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']), 
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print df.loc['b']

其 **输出** 如下:

one 2.0
two 2.0
Name: b, dtype: float64

结果是一个系列,其标签作为DataFrame的列名。并且,该系列的名称是检索它的标签。

按整数位置选择

可以通过将整数位置传递给iloc函数来选择行。

import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print df.iloc[2]

其 **输出** 如下:

one   3.0
two   3.0
Name: c, dtype: float64

切片行

可以使用“:”运算符选择多行。

import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']), 
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print df[2:4]

其 **输出** 如下:

   one  two
c  3.0    3
d  NaN    4

添加行

使用append函数将新行添加到DataFrame。此函数将在末尾附加行。

import pandas as pd

df = pd.DataFrame([[1, 2], [3, 4]], columns = ['a','b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns = ['a','b'])

df = df.append(df2)
print df

其 **输出** 如下:

   a  b
0  1  2
1  3  4
0  5  6
1  7  8

删除行

使用索引标签从DataFrame中删除或删除行。如果标签重复,则将删除多行。

如果您观察到,在上例中,标签是重复的。让我们删除一个标签,看看将删除多少行。

import pandas as pd

df = pd.DataFrame([[1, 2], [3, 4]], columns = ['a','b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns = ['a','b'])

df = df.append(df2)

# Drop rows with label 0
df = df.drop(0)

print df

其 **输出** 如下:

  a b
1 3 4
1 7 8

在上例中,删除了两行,因为这两行包含相同的标签0。

Python Pandas - Panel

面板是一个三维数据容器。术语面板数据源于计量经济学,并且部分地决定了pandas的名称——pan(el)-da(ta)-s

这三个轴的名称旨在为描述涉及面板数据的操作赋予一些语义含义。它们是:

  • items——轴0,每个项目对应于内部包含的DataFrame。

  • major_axis——轴1,它是每个DataFrame的索引(行)。

  • minor_axis——轴2,它是每个DataFrame的列。

pandas.Panel()

可以使用以下构造函数创建面板:

pandas.Panel(data, items, major_axis, minor_axis, dtype, copy)

构造函数的参数如下:

参数 描述
data 数据采用多种形式,例如ndarray、series、map、列表、dict、常量以及另一个DataFrame
items axis=0
major_axis axis=1
minor_axis axis=2
dtype 每列的数据类型
copy 复制数据。默认值,false

创建面板

可以使用多种方法创建面板,例如:

  • 从ndarrays
  • 从DataFrame的字典

从3D ndarray

# creating an empty panel
import pandas as pd
import numpy as np

data = np.random.rand(2,4,5)
p = pd.Panel(data)
print p

其 **输出** 如下:

<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 4 (major_axis) x 5 (minor_axis)
Items axis: 0 to 1
Major_axis axis: 0 to 3
Minor_axis axis: 0 to 4

注意——观察空面板和上述面板的维度,所有对象都不同。

从DataFrame对象的字典

#creating an empty panel
import pandas as pd
import numpy as np

data = {'Item1' : pd.DataFrame(np.random.randn(4, 3)), 
   'Item2' : pd.DataFrame(np.random.randn(4, 2))}
p = pd.Panel(data)
print p

其 **输出** 如下:

Dimensions: 2 (items) x 4 (major_axis) x 3 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 0 to 3
Minor_axis axis: 0 to 2

创建空面板

可以使用Panel构造函数创建空面板,如下所示:

#creating an empty panel
import pandas as pd
p = pd.Panel()
print p

其 **输出** 如下:

<class 'pandas.core.panel.Panel'>
Dimensions: 0 (items) x 0 (major_axis) x 0 (minor_axis)
Items axis: None
Major_axis axis: None
Minor_axis axis: None

从面板中选择数据

使用以下方法从面板中选择数据:

  • Items
  • Major_axis
  • Minor_axis

使用Items

# creating an empty panel
import pandas as pd
import numpy as np
data = {'Item1' : pd.DataFrame(np.random.randn(4, 3)), 
   'Item2' : pd.DataFrame(np.random.randn(4, 2))}
p = pd.Panel(data)
print p['Item1']

其 **输出** 如下:

            0          1          2
0    0.488224  -0.128637   0.930817
1    0.417497   0.896681   0.576657
2   -2.775266   0.571668   0.290082
3   -0.400538  -0.144234   1.110535

我们有两个项目,我们检索了item1。结果是一个DataFrame,具有4行和3列,它们是Major_axisMinor_axis维度。

使用major_axis

可以使用方法panel.major_axis(index)访问数据。

# creating an empty panel
import pandas as pd
import numpy as np
data = {'Item1' : pd.DataFrame(np.random.randn(4, 3)), 
   'Item2' : pd.DataFrame(np.random.randn(4, 2))}
p = pd.Panel(data)
print p.major_xs(1)

其 **输出** 如下:

      Item1       Item2
0   0.417497    0.748412
1   0.896681   -0.557322
2   0.576657       NaN

使用minor_axis

可以使用方法panel.minor_axis(index)访问数据。

# creating an empty panel
import pandas as pd
import numpy as np
data = {'Item1' : pd.DataFrame(np.random.randn(4, 3)), 
   'Item2' : pd.DataFrame(np.random.randn(4, 2))}
p = pd.Panel(data)
print p.minor_xs(1)

其 **输出** 如下:

       Item1       Item2
0   -0.128637   -1.047032
1    0.896681   -0.557322
2    0.571668    0.431953
3   -0.144234    1.302466

注意——观察维度的变化。

Python Pandas - 基本功能

到目前为止,我们了解了三种Pandas数据结构以及如何创建它们。由于DataFrame在实时数据处理中的重要性,我们将主要关注DataFrame对象,并讨论其他一些数据结构。

Series基本功能

序号 属性或方法和描述
1

axes

返回行轴标签的列表

2

dtype

返回对象的dtype。

3

empty

如果Series为空,则返回True。

4

ndim

返回底层数据的维度数,定义为1。

5

size

返回底层数据中的元素数。

6

values

将Series作为ndarray返回。

7

head()

返回前n行。

8

tail()

返回最后n行。

现在让我们创建一个Series,看看上面所有表格化的属性操作。

示例

import pandas as pd
import numpy as np

#Create a series with 100 random numbers
s = pd.Series(np.random.randn(4))
print s

其 **输出** 如下:

0   0.967853
1  -0.148368
2  -1.395906
3  -1.758394
dtype: float64

axes

返回Series标签的列表。

import pandas as pd
import numpy as np

#Create a series with 100 random numbers
s = pd.Series(np.random.randn(4))
print ("The axes are:")
print s.axes

其 **输出** 如下:

The axes are:
[RangeIndex(start=0, stop=4, step=1)]

上述结果是从0到5的值列表的紧凑格式,即[0,1,2,3,4]。

empty

返回布尔值,表示对象是否为空;True表示对象为空。

import pandas as pd
import numpy as np

#Create a series with 100 random numbers
s = pd.Series(np.random.randn(4))
print ("Is the Object empty?")
print s.empty

其 **输出** 如下:

Is the Object empty?
False

ndim

返回对象的维度数。根据定义,Series是一维数据结构,因此它返回

import pandas as pd
import numpy as np

#Create a series with 4 random numbers
s = pd.Series(np.random.randn(4))
print s

print ("The dimensions of the object:")
print s.ndim

其 **输出** 如下:

0   0.175898
1   0.166197
2  -0.609712
3  -1.377000
dtype: float64

The dimensions of the object:
1

size

返回Series的大小(长度)。

import pandas as pd
import numpy as np

#Create a series with 4 random numbers
s = pd.Series(np.random.randn(2))
print s
print ("The size of the object:")
print s.size

其 **输出** 如下:

0   3.078058
1  -1.207803
dtype: float64

The size of the object:
2

values

将Series中的实际数据作为数组返回。

import pandas as pd
import numpy as np

#Create a series with 4 random numbers
s = pd.Series(np.random.randn(4))
print s

print ("The actual data series is:")
print s.values

其 **输出** 如下:

0   1.787373
1  -0.605159
2   0.180477
3  -0.140922
dtype: float64

The actual data series is:
[ 1.78737302 -0.60515881 0.18047664 -0.1409218 ]

Head & Tail

要查看Series或DataFrame对象的小样本,请使用head()和tail()方法。

head()返回前n行(观察索引值)。要显示的元素默认数量为五个,但您可以传递自定义数量。

import pandas as pd
import numpy as np

#Create a series with 4 random numbers
s = pd.Series(np.random.randn(4))
print ("The original series is:")
print s

print ("The first two rows of the data series:")
print s.head(2)

其 **输出** 如下:

The original series is:
0   0.720876
1  -0.765898
2   0.479221
3  -0.139547
dtype: float64

The first two rows of the data series:
0   0.720876
1  -0.765898
dtype: float64

tail()返回最后n行(观察索引值)。要显示的元素默认数量为五个,但您可以传递自定义数量。

import pandas as pd
import numpy as np

#Create a series with 4 random numbers
s = pd.Series(np.random.randn(4))
print ("The original series is:")
print s

print ("The last two rows of the data series:")
print s.tail(2)

其 **输出** 如下:

The original series is:
0 -0.655091
1 -0.881407
2 -0.608592
3 -2.341413
dtype: float64

The last two rows of the data series:
2 -0.608592
3 -2.341413
dtype: float64

DataFrame基本功能

现在让我们了解什么是DataFrame基本功能。下表列出了有助于DataFrame基本功能的重要属性或方法。

序号 属性或方法和描述
1

T

转置行和列。

2

axes

返回一个列表,其中仅包含行轴标签和列轴标签作为成员。

3

dtypes

返回此对象中的dtypes。

4

empty

如果NDFrame完全为空[没有项目];如果任何轴的长度为0,则为True。

5

ndim

轴/数组维数。

6

shape

返回表示DataFrame维度的元组。

7

size

NDFrame中的元素数。

8

values

NDFrame的NumPy表示。

9

head()

返回前n行。

10

tail()

返回最后n行。

现在让我们创建一个DataFrame,看看上面提到的所有属性是如何操作的。

示例

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

#Create a DataFrame
df = pd.DataFrame(d)
print ("Our data series is:")
print df

其 **输出** 如下:

Our data series is:
    Age   Name    Rating
0   25    Tom     4.23
1   26    James   3.24
2   25    Ricky   3.98
3   23    Vin     2.56
4   30    Steve   3.20
5   29    Smith   4.60
6   23    Jack    3.80

T(转置)

返回DataFrame的转置。行和列将互换。

import pandas as pd
import numpy as np
 
# Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

# Create a DataFrame
df = pd.DataFrame(d)
print ("The transpose of the data series is:")
print df.T

其 **输出** 如下:

The transpose of the data series is:
         0     1       2      3      4      5       6
Age      25    26      25     23     30     29      23
Name     Tom   James   Ricky  Vin    Steve  Smith   Jack
Rating   4.23  3.24    3.98   2.56   3.2    4.6     3.8

axes

返回行轴标签和列轴标签的列表。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

#Create a DataFrame
df = pd.DataFrame(d)
print ("Row axis labels and column axis labels are:")
print df.axes

其 **输出** 如下:

Row axis labels and column axis labels are:

[RangeIndex(start=0, stop=7, step=1), Index([u'Age', u'Name', u'Rating'],
dtype='object')]

dtypes

返回每一列的数据类型。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

#Create a DataFrame
df = pd.DataFrame(d)
print ("The data types of each column are:")
print df.dtypes

其 **输出** 如下:

The data types of each column are:
Age     int64
Name    object
Rating  float64
dtype: object

empty

返回布尔值,表示对象是否为空;True表示对象为空。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}
 
#Create a DataFrame
df = pd.DataFrame(d)
print ("Is the object empty?")
print df.empty

其 **输出** 如下:

Is the object empty?
False

ndim

返回对象的维度数。根据定义,DataFrame是一个二维对象。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

#Create a DataFrame
df = pd.DataFrame(d)
print ("Our object is:")
print df
print ("The dimension of the object is:")
print df.ndim

其 **输出** 如下:

Our object is:
      Age    Name     Rating
0     25     Tom      4.23
1     26     James    3.24
2     25     Ricky    3.98
3     23     Vin      2.56
4     30     Steve    3.20
5     29     Smith    4.60
6     23     Jack     3.80

The dimension of the object is:
2

shape

返回一个元组,表示 DataFrame 的维度。元组 (a,b),其中 a 表示行数,b 表示列数。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}
 
#Create a DataFrame
df = pd.DataFrame(d)
print ("Our object is:")
print df
print ("The shape of the object is:")
print df.shape

其 **输出** 如下:

Our object is:
   Age   Name    Rating
0  25    Tom     4.23
1  26    James   3.24
2  25    Ricky   3.98
3  23    Vin     2.56
4  30    Steve   3.20
5  29    Smith   4.60
6  23    Jack    3.80

The shape of the object is:
(7, 3)

size

返回 DataFrame 中元素的个数。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}
 
#Create a DataFrame
df = pd.DataFrame(d)
print ("Our object is:")
print df
print ("The total number of elements in our object is:")
print df.size

其 **输出** 如下:

Our object is:
    Age   Name    Rating
0   25    Tom     4.23
1   26    James   3.24
2   25    Ricky   3.98
3   23    Vin     2.56
4   30    Steve   3.20
5   29    Smith   4.60
6   23    Jack    3.80

The total number of elements in our object is:
21

values

将 DataFrame 中的实际数据作为NDarray返回。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}
 
#Create a DataFrame
df = pd.DataFrame(d)
print ("Our object is:")
print df
print ("The actual data in our data frame is:")
print df.values

其 **输出** 如下:

Our object is:
    Age   Name    Rating
0   25    Tom     4.23
1   26    James   3.24
2   25    Ricky   3.98
3   23    Vin     2.56
4   30    Steve   3.20
5   29    Smith   4.60
6   23    Jack    3.80
The actual data in our data frame is:
[[25 'Tom' 4.23]
[26 'James' 3.24]
[25 'Ricky' 3.98]
[23 'Vin' 2.56]
[30 'Steve' 3.2]
[29 'Smith' 4.6]
[23 'Jack' 3.8]]

Head & Tail

要查看 DataFrame 对象的小样本,可以使用head()和 tail() 方法。head()返回前n行(观察索引值)。默认显示的元素个数为五个,但您可以传递自定义个数。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

#Create a DataFrame
df = pd.DataFrame(d)
print ("Our data frame is:")
print df
print ("The first two rows of the data frame is:")
print df.head(2)

其 **输出** 如下:

Our data frame is:
    Age   Name    Rating
0   25    Tom     4.23
1   26    James   3.24
2   25    Ricky   3.98
3   23    Vin     2.56
4   30    Steve   3.20
5   29    Smith   4.60
6   23    Jack    3.80

The first two rows of the data frame is:
   Age   Name   Rating
0  25    Tom    4.23
1  26    James  3.24

tail()返回最后n行(观察索引值)。默认显示的元素个数为五个,但您可以传递自定义个数。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack']),
   'Age':pd.Series([25,26,25,23,30,29,23]), 
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}
 
#Create a DataFrame
df = pd.DataFrame(d)
print ("Our data frame is:")
print df
print ("The last two rows of the data frame is:")
print df.tail(2)

其 **输出** 如下:

Our data frame is:
    Age   Name    Rating
0   25    Tom     4.23
1   26    James   3.24
2   25    Ricky   3.98
3   23    Vin     2.56
4   30    Steve   3.20
5   29    Smith   4.60
6   23    Jack    3.80

The last two rows of the data frame is:
    Age   Name    Rating
5   29    Smith    4.6
6   23    Jack     3.8

Python Pandas - 描述性统计

许多方法共同计算 DataFrame 的描述性统计和其他相关操作。大多数是聚合函数,例如sum(),mean(),但有些函数,例如sumsum(),会生成相同大小的对象。一般来说,这些方法都接受一个axis参数,就像ndarray.{sum, std, ...}一样,但是轴可以由名称或整数指定。

  • DataFrame − “index”(axis=0,默认),“columns”(axis=1)

让我们创建一个 DataFrame,并在本章中使用此对象进行所有操作。

示例

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df

其 **输出** 如下:

    Age  Name   Rating
0   25   Tom     4.23
1   26   James   3.24
2   25   Ricky   3.98
3   23   Vin     2.56
4   30   Steve   3.20
5   29   Smith   4.60
6   23   Jack    3.80
7   34   Lee     3.78
8   40   David   2.98
9   30   Gasper  4.80
10  51   Betina  4.10
11  46   Andres  3.65

sum()

返回请求轴的值之和。默认情况下,轴为索引 (axis=0)。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.sum()

其 **输出** 如下:

Age                                                    382
Name     TomJamesRickyVinSteveSmithJackLeeDavidGasperBe...
Rating                                               44.92
dtype: object

每列分别相加(字符串被追加)。

axis=1

此语法将给出如下所示的输出。

import pandas as pd
import numpy as np
 
#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}
 
#Create a DataFrame
df = pd.DataFrame(d)
print df.sum(1)

其 **输出** 如下:

0    29.23
1    29.24
2    28.98
3    25.56
4    33.20
5    33.60
6    26.80
7    37.78
8    42.98
9    34.80
10   55.10
11   49.65
dtype: float64

mean()

返回平均值。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.mean()

其 **输出** 如下:

Age       31.833333
Rating     3.743333
dtype: float64

std()

返回数值列的贝塞尔标准差。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.std()

其 **输出** 如下:

Age       9.232682
Rating    0.661628
dtype: float64

函数与说明

现在让我们了解 Python Pandas 中描述性统计下的函数。下表列出了重要的函数:

序号 函数 描述
1 count() 非空观察值的个数
2 sum() 值的总和
3 mean() 值的平均值
4 median() 值的中位数
5 mode() 值的众数
6 std() 值的标准差
7 min() 最小值
8 max() 最大值
9 abs() 绝对值
10 prod() 值的乘积
11 cumsum() 累积和
12 cumprod() 累积乘积

注意 − 由于 DataFrame 是异构数据结构,通用操作并不适用于所有函数。

  • sum(),cumsum()这样的函数可以处理数值和字符(或)字符串数据元素,而不会出现任何错误。尽管在实践中,字符聚合通常不被使用,但这些函数不会抛出任何异常。

  • abs(),cumprod()这样的函数在 DataFrame 包含字符或字符串数据时会抛出异常,因为无法执行此类操作。

数据汇总

describe()函数计算与 DataFrame 列相关的统计摘要。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.describe()

其 **输出** 如下:

               Age         Rating
count    12.000000      12.000000
mean     31.833333       3.743333
std       9.232682       0.661628
min      23.000000       2.560000
25%      25.000000       3.230000
50%      29.500000       3.790000
75%      35.500000       4.132500
max      51.000000       4.800000

此函数给出mean、stdIQR值。并且,该函数排除字符列并给出关于数值列的摘要。'include' 是一个参数,用于传递有关需要考虑哪些列进行汇总的必要信息。接受值列表;默认为 'number'。

  • object − 汇总字符串列
  • number − 汇总数值列
  • all − 汇总所有列(不应将其作为列表值传递)

现在,在程序中使用以下语句并检查输出:

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.describe(include=['object'])

其 **输出** 如下:

          Name
count       12
unique      12
top      Ricky
freq         1

现在,使用以下语句并检查输出:

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df. describe(include='all')

其 **输出** 如下:

          Age          Name       Rating
count   12.000000        12    12.000000
unique        NaN        12          NaN
top           NaN     Ricky          NaN
freq          NaN         1          NaN
mean    31.833333       NaN     3.743333
std      9.232682       NaN     0.661628
min     23.000000       NaN     2.560000
25%     25.000000       NaN     3.230000
50%     29.500000       NaN     3.790000
75%     35.500000       NaN     4.132500
max     51.000000       NaN     4.800000

Python Pandas - 函数应用

要将您自己或其他库的函数应用于 Pandas 对象,您应该了解三个重要的方法。以下讨论了这些方法。要使用的方法取决于您的函数是否期望对整个 DataFrame、行或列方式或元素方式进行操作。

  • 表级函数应用:pipe()
  • 行或列级函数应用:apply()
  • 元素级函数应用:applymap()

表级函数应用

可以通过传递函数和适当数量的参数作为 pipe 参数来执行自定义操作。因此,操作是在整个 DataFrame 上执行的。

例如,将值 2 加到 DataFrame 中的所有元素。然后,

adder 函数

adder 函数将两个数值作为参数相加并返回和。

def adder(ele1,ele2):
   return ele1+ele2

我们现在将使用自定义函数对 DataFrame 进行操作。

df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
df.pipe(adder,2)

让我们看看完整的程序:

import pandas as pd
import numpy as np

def adder(ele1,ele2):
   return ele1+ele2

df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
df.pipe(adder,2)
print df.apply(np.mean)

其 **输出** 如下:

        col1       col2       col3
0   2.176704   2.219691   1.509360
1   2.222378   2.422167   3.953921
2   2.241096   1.135424   2.696432
3   2.355763   0.376672   1.182570
4   2.308743   2.714767   2.130288

行或列级函数应用

可以使用apply()方法沿 DataFrame 或 Panel 的轴应用任意函数,该方法与描述性统计方法一样,接受可选的 axis 参数。默认情况下,操作按列执行,将每一列作为类数组处理。

示例 1

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
df.apply(np.mean)
print df.apply(np.mean)

其 **输出** 如下:

col1   -0.288022
col2    1.044839
col3   -0.187009
dtype: float64

通过传递axis参数,可以按行执行操作。

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
df.apply(np.mean,axis=1)
print df.apply(np.mean)

其 **输出** 如下:

col1    0.034093
col2   -0.152672
col3   -0.229728
dtype: float64  

示例3

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
df.apply(lambda x: x.max() - x.min())
print df.apply(np.mean)

其 **输出** 如下:

col1   -0.167413
col2   -0.370495
col3   -0.707631
dtype: float64

元素级函数应用

并非所有函数都可以向量化(既不是返回另一个数组的 NumPy 数组,也不是任何值),DataFrame 上的applymap()方法和Series上的analogously map()方法接受任何接受单个值并返回单个值的 Python 函数。

示例 1

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])

# My custom function
df['col1'].map(lambda x:x*100)
print df.apply(np.mean)

其 **输出** 如下:

col1    0.480742
col2    0.454185
col3    0.266563
dtype: float64

示例 2

import pandas as pd
import numpy as np

# My custom function
df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
df.applymap(lambda x:x*100)
print df.apply(np.mean)

其 **输出** 如下:

col1    0.395263
col2    0.204418
col3   -0.795188
dtype: float64

Python Pandas - 重新索引

重新索引更改 DataFrame 的行标签和列标签。重新索引意味着使数据符合特定轴上给定标签集。

可以通过索引完成多个操作,例如:

  • 重新排序现有数据以匹配新的标签集。

  • 在标签位置插入缺失值 (NA) 标记,这些位置不存在该标签的数据。

示例

import pandas as pd
import numpy as np

N=20

df = pd.DataFrame({
   'A': pd.date_range(start='2016-01-01',periods=N,freq='D'),
   'x': np.linspace(0,stop=N-1,num=N),
   'y': np.random.rand(N),
   'C': np.random.choice(['Low','Medium','High'],N).tolist(),
   'D': np.random.normal(100, 10, size=(N)).tolist()
})

#reindex the DataFrame
df_reindexed = df.reindex(index=[0,2,5], columns=['A', 'C', 'B'])

print df_reindexed

其 **输出** 如下:

            A    C     B
0  2016-01-01  Low   NaN
2  2016-01-03  High  NaN
5  2016-01-06  Low   NaN

与其他对象对齐重新索引

您可能希望获取一个对象并将其轴重新索引为与另一个对象相同的标签。考虑以下示例以了解相同内容。

示例

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(10,3),columns=['col1','col2','col3'])
df2 = pd.DataFrame(np.random.randn(7,3),columns=['col1','col2','col3'])

df1 = df1.reindex_like(df2)
print df1

其 **输出** 如下:

          col1         col2         col3
0    -2.467652    -1.211687    -0.391761
1    -0.287396     0.522350     0.562512
2    -0.255409    -0.483250     1.866258
3    -1.150467    -0.646493    -0.222462
4     0.152768    -2.056643     1.877233
5    -1.155997     1.528719    -1.343719
6    -1.015606    -1.245936    -0.295275

注意 − 在这里,df1 DataFrame 被更改并像df2一样重新索引。列名应该匹配,否则整个列标签将添加 NAN。

重新索引时的填充

reindex()接受一个可选参数 method,它是一个填充方法,其值如下:

  • pad/ffill − 向前填充值

  • bfill/backfill − 向后填充值

  • nearest − 从最近的索引值填充

示例

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])
df2 = pd.DataFrame(np.random.randn(2,3),columns=['col1','col2','col3'])

# Padding NAN's
print df2.reindex_like(df1)

# Now Fill the NAN's with preceding Values
print ("Data Frame with Forward Fill:")
print df2.reindex_like(df1,method='ffill')

其 **输出** 如下:

         col1        col2       col3
0    1.311620   -0.707176   0.599863
1   -0.423455   -0.700265   1.133371
2         NaN         NaN        NaN
3         NaN         NaN        NaN
4         NaN         NaN        NaN
5         NaN         NaN        NaN

Data Frame with Forward Fill:
         col1        col2        col3
0    1.311620   -0.707176    0.599863
1   -0.423455   -0.700265    1.133371
2   -0.423455   -0.700265    1.133371
3   -0.423455   -0.700265    1.133371
4   -0.423455   -0.700265    1.133371
5   -0.423455   -0.700265    1.133371

注意 − 最后四行已填充。

重新索引时的填充限制

limit 参数提供了对重新索引时填充的额外控制。Limit 指定连续匹配的最大计数。让我们考虑以下示例以了解相同内容:

示例

import pandas as pd
import numpy as np
 
df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])
df2 = pd.DataFrame(np.random.randn(2,3),columns=['col1','col2','col3'])

# Padding NAN's
print df2.reindex_like(df1)

# Now Fill the NAN's with preceding Values
print ("Data Frame with Forward Fill limiting to 1:")
print df2.reindex_like(df1,method='ffill',limit=1)

其 **输出** 如下:

         col1        col2        col3
0    0.247784    2.128727    0.702576
1   -0.055713   -0.021732   -0.174577
2         NaN         NaN         NaN
3         NaN         NaN         NaN
4         NaN         NaN         NaN
5         NaN         NaN         NaN

Data Frame with Forward Fill limiting to 1:
         col1        col2        col3
0    0.247784    2.128727    0.702576
1   -0.055713   -0.021732   -0.174577
2   -0.055713   -0.021732   -0.174577
3         NaN         NaN         NaN
4         NaN         NaN         NaN
5         NaN         NaN         NaN

注意 − 请注意,只有第 7 行由前面的第 6 行填充。然后,其余行保持不变。

重命名

rename() 方法允许您根据某些映射(字典或 Series)或任意函数重新标记轴。

让我们考虑以下示例来理解这一点:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])
print df1

print ("After renaming the rows and columns:")
print df1.rename(columns={'col1' : 'c1', 'col2' : 'c2'},
index = {0 : 'apple', 1 : 'banana', 2 : 'durian'})

其 **输出** 如下:

         col1        col2        col3
0    0.486791    0.105759    1.540122
1   -0.990237    1.007885   -0.217896
2   -0.483855   -1.645027   -1.194113
3   -0.122316    0.566277   -0.366028
4   -0.231524   -0.721172   -0.112007
5    0.438810    0.000225    0.435479

After renaming the rows and columns:
                c1          c2        col3
apple     0.486791    0.105759    1.540122
banana   -0.990237    1.007885   -0.217896
durian   -0.483855   -1.645027   -1.194113
3        -0.122316    0.566277   -0.366028
4        -0.231524   -0.721172   -0.112007
5         0.438810    0.000225    0.435479

rename() 方法提供一个inplace命名参数,默认情况下为 False 并复制底层数据。传递inplace=True以就地重命名数据。

Python Pandas - 迭代

对 Pandas 对象的基本迭代的行为取决于类型。当迭代 Series 时,它被视为类数组,基本迭代产生值。其他数据结构,如 DataFrame 和 Panel,遵循在对象的上迭代的类字典约定。

简而言之,基本迭代(对于对象中的i)产生:

  • Series − 值

  • DataFrame − 列标签

  • Panel − 项目标签

迭代 DataFrame

迭代 DataFrame 会给出列名。让我们考虑以下示例来了解相同内容。

import pandas as pd
import numpy as np
 
N=20
df = pd.DataFrame({
   'A': pd.date_range(start='2016-01-01',periods=N,freq='D'),
   'x': np.linspace(0,stop=N-1,num=N),
   'y': np.random.rand(N),
   'C': np.random.choice(['Low','Medium','High'],N).tolist(),
   'D': np.random.normal(100, 10, size=(N)).tolist()
   })

for col in df:
   print col

其 **输出** 如下:

A
C
D
x
y

要迭代 DataFrame 的行,我们可以使用以下函数:

  • iteritems() − 迭代 (键,值) 对

  • iterrows() − 将行迭代为 (索引,序列) 对

  • itertuples() − 将行迭代为命名元组

iteritems()

将每一列迭代为键值对,标签作为键,列值作为 Series 对象。

import pandas as pd
import numpy as np
 
df = pd.DataFrame(np.random.randn(4,3),columns=['col1','col2','col3'])
for key,value in df.iteritems():
   print key,value

其 **输出** 如下:

col1 0    0.802390
1    0.324060
2    0.256811
3    0.839186
Name: col1, dtype: float64

col2 0    1.624313
1   -1.033582
2    1.796663
3    1.856277
Name: col2, dtype: float64

col3 0   -0.022142
1   -0.230820
2    1.160691
3   -0.830279
Name: col3, dtype: float64

观察,每一列都作为 Series 中的键值对单独迭代。

iterrows()

iterrows() 返回迭代器,生成每个索引值以及包含每一行数据的序列。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(4,3),columns = ['col1','col2','col3'])
for row_index,row in df.iterrows():
   print row_index,row

其 **输出** 如下:

0  col1    1.529759
   col2    0.762811
   col3   -0.634691
Name: 0, dtype: float64

1  col1   -0.944087
   col2    1.420919
   col3   -0.507895
Name: 1, dtype: float64
 
2  col1   -0.077287
   col2   -0.858556
   col3   -0.663385
Name: 2, dtype: float64
3  col1    -1.638578
   col2     0.059866
   col3     0.493482
Name: 3, dtype: float64

注意 − 因为iterrows()迭代行,所以它不会保留跨行的数 据类型。0,1,2 是行索引,col1,col2,col3 是列索引。

itertuples()

itertuples() 方法将返回一个迭代器,为 DataFrame 中的每一行生成一个命名元组。元组的第一个元素将是行的相应索引值,其余值是行值。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(4,3),columns = ['col1','col2','col3'])
for row in df.itertuples():
    print row

其 **输出** 如下:

Pandas(Index=0, col1=1.5297586201375899, col2=0.76281127433814944, col3=-
0.6346908238310438)

Pandas(Index=1, col1=-0.94408735763808649, col2=1.4209186418359423, col3=-
0.50789517967096232)

Pandas(Index=2, col1=-0.07728664756791935, col2=-0.85855574139699076, col3=-
0.6633852507207626)

Pandas(Index=3, col1=0.65734942534106289, col2=-0.95057710432604969,
col3=0.80344487462316527)

注意 − 迭代时不要尝试修改任何对象。迭代旨在用于读取,迭代器返回原始对象的副本(视图),因此更改不会反映在原始对象上。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(4,3),columns = ['col1','col2','col3'])

for index, row in df.iterrows():
   row['a'] = 10
print df

其 **输出** 如下:

        col1       col2       col3
0  -1.739815   0.735595  -0.295589
1   0.635485   0.106803   1.527922
2  -0.939064   0.547095   0.038585
3  -1.016509  -0.116580  -0.523158

观察,没有反映任何变化。

Python Pandas - 排序

Pandas 中有两种排序方式。它们是:

  • 按标签
  • 按实际值

让我们考虑一个带有输出的示例。

import pandas as pd
import numpy as np

unsorted_df=pd.DataFrame(np.random.randn(10,2),index=[1,4,6,2,3,5,9,8,0,7],colu
mns=['col2','col1'])
print unsorted_df

其 **输出** 如下:

        col2       col1
1  -2.063177   0.537527
4   0.142932  -0.684884
6   0.012667  -0.389340
2  -0.548797   1.848743
3  -1.044160   0.837381
5   0.385605   1.300185
9   1.031425  -1.002967
8  -0.407374  -0.435142
0   2.237453  -1.067139
7  -1.445831  -1.701035

unsorted_df中,标签未排序。让我们看看如何对这些进行排序。

按标签

使用sort_index()方法,通过传递轴参数和排序顺序,可以对 DataFrame 进行排序。默认情况下,按升序对行标签进行排序。

import pandas as pd
import numpy as np

unsorted_df = pd.DataFrame(np.random.randn(10,2),index=[1,4,6,2,3,5,9,8,0,7],colu
   mns = ['col2','col1'])

sorted_df=unsorted_df.sort_index()
print sorted_df

其 **输出** 如下:

        col2       col1
0   0.208464   0.627037
1   0.641004   0.331352
2  -0.038067  -0.464730
3  -0.638456  -0.021466
4   0.014646  -0.737438
5  -0.290761  -1.669827
6  -0.797303  -0.018737
7   0.525753   1.628921
8  -0.567031   0.775951
9   0.060724  -0.322425

排序顺序

通过向 ascending 参数传递布尔值,可以控制排序顺序。让我们考虑以下示例以了解相同内容。

import pandas as pd
import numpy as np

unsorted_df = pd.DataFrame(np.random.randn(10,2),index=[1,4,6,2,3,5,9,8,0,7],colu
   mns = ['col2','col1'])

sorted_df = unsorted_df.sort_index(ascending=False)
print sorted_df

其 **输出** 如下:

         col2        col1
9    0.825697    0.374463
8   -1.699509    0.510373
7   -0.581378    0.622958
6   -0.202951    0.954300
5   -1.289321   -1.551250
4    1.302561    0.851385
3   -0.157915   -0.388659
2   -1.222295    0.166609
1    0.584890   -0.291048
0    0.668444   -0.061294

排序列

通过传递值为 0 或 1 的轴参数,可以对列标签进行排序。默认情况下,axis=0,按行排序。让我们考虑以下示例以了解相同内容。

import pandas as pd
import numpy as np
 
unsorted_df = pd.DataFrame(np.random.randn(10,2),index=[1,4,6,2,3,5,9,8,0,7],colu
   mns = ['col2','col1'])
 
sorted_df=unsorted_df.sort_index(axis=1)

print sorted_df

其 **输出** 如下:

         col1        col2
1   -0.291048    0.584890
4    0.851385    1.302561
6    0.954300   -0.202951
2    0.166609   -1.222295
3   -0.388659   -0.157915
5   -1.551250   -1.289321
9    0.374463    0.825697
8    0.510373   -1.699509
0   -0.061294    0.668444
7    0.622958   -0.581378

按值

与索引排序类似,sort_values()是按值排序的方法。它接受一个 'by' 参数,该参数将使用 DataFrame 的列名来排序值。

import pandas as pd
import numpy as np

unsorted_df = pd.DataFrame({'col1':[2,1,1,1],'col2':[1,3,2,4]})
   sorted_df = unsorted_df.sort_values(by='col1')

print sorted_df

其 **输出** 如下:

   col1  col2
1    1    3
2    1    2
3    1    4
0    2    1

观察,col1 值已排序,相应的 col2 值和行索引将与 col1 一起更改。因此,它们看起来未排序。

'by' 参数接受列值的列表。

import pandas as pd
import numpy as np

unsorted_df = pd.DataFrame({'col1':[2,1,1,1],'col2':[1,3,2,4]})
   sorted_df = unsorted_df.sort_values(by=['col1','col2'])

print sorted_df

其 **输出** 如下:

  col1 col2
2   1   2
1   1   3
3   1   4
0   2   1

排序算法

sort_values()提供了一个从 mergesort、heapsort 和 quicksort 中选择算法的规定。Mergesort 是唯一稳定的算法。

import pandas as pd
import numpy as np

unsorted_df = pd.DataFrame({'col1':[2,1,1,1],'col2':[1,3,2,4]})
sorted_df = unsorted_df.sort_values(by='col1' ,kind='mergesort')

print sorted_df

其 **输出** 如下:

  col1 col2
1    1    3
2    1    2
3    1    4
0    2    1

Python Pandas - 使用文本数据

在本章中,我们将讨论使用我们的基本 Series/Index 的字符串操作。在后续章节中,我们将学习如何在 DataFrame 上应用这些字符串函数。

Pandas 提供了一组字符串函数,使操作字符串数据变得容易。最重要的是,这些函数忽略(或排除)缺失/NaN 值。

几乎所有这些方法都与 Python 字符串函数一起使用(参考:https://docs.pythonlang.cn/3/library/stdtypes.html#string-methods)。因此,将 Series 对象转换为 String 对象,然后执行操作。

现在让我们看看每个操作是如何执行的。

序号 函数与说明
1

lower()

将 Series/Index 中的字符串转换为小写。

2

upper()

将 Series/Index 中的字符串转换为大写。

3

len()

计算字符串长度。

4

strip()

用于去除Series/索引中每个字符串两侧的空格(包括换行符)。

5

split(' ')

使用给定的模式分割每个字符串。

6

cat(sep=' ')

使用给定的分隔符连接Series/索引元素。

7

get_dummies()

返回包含独热编码值的DataFrame。

8

contains(pattern)

如果元素包含子字符串,则为每个元素返回布尔值True,否则返回False。

9

replace(a,b)

将值a替换为值b

10

repeat(value)

将每个元素重复指定次数。

11

count(pattern)

返回每个元素中模式出现的次数。

12

startswith(pattern)

如果Series/索引中的元素以该模式开头,则返回True。

13

endswith(pattern)

如果Series/索引中的元素以该模式结尾,则返回True。

14

find(pattern)

返回模式第一次出现的第一个位置。

15

findall(pattern)

返回模式所有出现位置的列表。

16

swapcase

交换大小写(小写变大写,大写变小写)。

17

islower()

检查Series/索引中每个字符串中的所有字符是否都小写。返回布尔值。

18

isupper()

检查Series/索引中每个字符串中的所有字符是否都大写。返回布尔值。

19

isnumeric()

检查Series/索引中每个字符串中的所有字符是否都是数字。返回布尔值。

现在让我们创建一个Series,看看以上所有函数是如何工作的。

import pandas as pd
import numpy as np

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234','SteveSmith'])

print s

其 **输出** 如下:

0            Tom
1   William Rick
2           John
3        Alber@t
4            NaN
5           1234
6    Steve Smith
dtype: object

lower()

import pandas as pd
import numpy as np

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234','SteveSmith'])

print s.str.lower()

其 **输出** 如下:

0            tom
1   william rick
2           john
3        alber@t
4            NaN
5           1234
6    steve smith
dtype: object

upper()

import pandas as pd
import numpy as np

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234','SteveSmith'])

print s.str.upper()

其 **输出** 如下:

0            TOM
1   WILLIAM RICK
2           JOHN
3        ALBER@T
4            NaN
5           1234
6    STEVE SMITH
dtype: object

len()

import pandas as pd
import numpy as np

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234','SteveSmith'])
print s.str.len()

其 **输出** 如下:

0    3.0
1   12.0
2    4.0
3    7.0
4    NaN
5    4.0
6   10.0
dtype: float64

strip()

import pandas as pd
import numpy as np
s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])
print s
print ("After Stripping:")
print s.str.strip()

其 **输出** 如下:

0            Tom
1   William Rick
2           John
3        Alber@t
dtype: object

After Stripping:
0            Tom
1   William Rick
2           John
3        Alber@t
dtype: object

split(pattern)

import pandas as pd
import numpy as np
s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])
print s
print ("Split Pattern:")
print s.str.split(' ')

其 **输出** 如下:

0            Tom
1   William Rick
2           John
3        Alber@t
dtype: object

Split Pattern:
0   [Tom, , , , , , , , , , ]
1   [, , , , , William, Rick]
2   [John]
3   [Alber@t]
dtype: object

cat(sep=pattern)

import pandas as pd
import numpy as np

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print s.str.cat(sep='_')

其 **输出** 如下:

Tom _ William Rick_John_Alber@t

get_dummies()

import pandas as pd
import numpy as np

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print s.str.get_dummies()

其 **输出** 如下:

   William Rick   Alber@t   John   Tom
0             0         0      0     1
1             1         0      0     0
2             0         0      1     0
3             0         1      0     0

contains ()

import pandas as pd

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print s.str.contains(' ')

其 **输出** 如下:

0   True
1   True
2   False
3   False
dtype: bool

replace(a,b)

import pandas as pd
s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])
print s
print ("After replacing @ with $:")
print s.str.replace('@','$')

其 **输出** 如下:

0   Tom
1   William Rick
2   John
3   Alber@t
dtype: object

After replacing @ with $:
0   Tom
1   William Rick
2   John
3   Alber$t
dtype: object

repeat(value)

import pandas as pd

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print s.str.repeat(2)

其 **输出** 如下:

0   Tom            Tom
1   William Rick   William Rick
2                  JohnJohn
3                  Alber@tAlber@t
dtype: object

count(pattern)

import pandas as pd
 
s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print ("The number of 'm's in each string:")
print s.str.count('m')

其 **输出** 如下:

The number of 'm's in each string:
0    1
1    1
2    0
3    0

startswith(pattern)

import pandas as pd

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print ("Strings that start with 'T':")
print s.str. startswith ('T')

其 **输出** 如下:

0  True
1  False
2  False
3  False
dtype: bool

endswith(pattern)

import pandas as pd
s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])
print ("Strings that end with 't':")
print s.str.endswith('t')

其 **输出** 如下:

Strings that end with 't':
0  False
1  False
2  False
3  True
dtype: bool

find(pattern)

import pandas as pd

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print s.str.find('e')

其 **输出** 如下:

0  -1
1  -1
2  -1
3   3
dtype: int64

“-1”表示元素中不存在此模式。

findall(pattern)

import pandas as pd

s = pd.Series(['Tom ', ' William Rick', 'John', 'Alber@t'])

print s.str.findall('e')

其 **输出** 如下:

0 []
1 []
2 []
3 [e]
dtype: object

空列表([])表示元素中不存在此模式。

swapcase()

import pandas as pd

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t'])
print s.str.swapcase()

其 **输出** 如下:

0  tOM
1  wILLIAM rICK
2  jOHN
3  aLBER@T
dtype: object

islower()

import pandas as pd

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t'])
print s.str.islower()

其 **输出** 如下:

0  False
1  False
2  False
3  False
dtype: bool

isupper()

import pandas as pd

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t'])

print s.str.isupper()

其 **输出** 如下:

0  False
1  False
2  False
3  False
dtype: bool

isnumeric()

import pandas as pd

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t'])

print s.str.isnumeric()

其 **输出** 如下:

0  False
1  False
2  False
3  False
dtype: bool

Python Pandas - 选项和自定义

Pandas提供API来定制其行为的某些方面,主要用于显示。

该API包含五个相关的函数,它们是:

  • get_option()
  • set_option()
  • reset_option()
  • describe_option()
  • option_context()

现在让我们了解这些函数是如何工作的。

get_option(param)

get_option接受单个参数并返回如下所示的值:

display.max_rows

显示默认值的数量。解释器读取此值,并以此值为显示行的上限。

import pandas as pd
print pd.get_option("display.max_rows")

其 **输出** 如下:

60

display.max_columns

显示默认值的数量。解释器读取此值,并以此值为显示行的上限。

import pandas as pd
print pd.get_option("display.max_columns")

其 **输出** 如下:

20

这里,60和20是默认配置参数值。

set_option(param,value)

set_option接受两个参数并将值设置为参数,如下所示:

display.max_rows

使用set_option(),我们可以更改要显示的默认行数。

import pandas as pd

pd.set_option("display.max_rows",80)

print pd.get_option("display.max_rows")

其 **输出** 如下:

80

display.max_columns

使用set_option(),我们可以更改要显示的默认行数。

import pandas as pd

pd.set_option("display.max_columns",30)

print pd.get_option("display.max_columns")

其 **输出** 如下:

30

reset_option(param)

reset_option接受一个参数并将值重置为默认值。

display.max_rows

使用reset_option(),我们可以将值改回要显示的默认行数。

import pandas as pd

pd.reset_option("display.max_rows")
print pd.get_option("display.max_rows")

其 **输出** 如下:

60

describe_option(param)

describe_option打印参数的描述。

display.max_rows

使用reset_option(),我们可以将值改回要显示的默认行数。

import pandas as pd
pd.describe_option("display.max_rows")

其 **输出** 如下:

display.max_rows : int
   If max_rows is exceeded, switch to truncate view. Depending on
   'large_repr', objects are either centrally truncated or printed as
   a summary view. 'None' value means unlimited.

   In case python/IPython is running in a terminal and `large_repr`
   equals 'truncate' this can be set to 0 and pandas will auto-detect
   the height of the terminal and print a truncated object which fits
   the screen height. The IPython notebook, IPython qtconsole, or
   IDLE do not run in a terminal and hence it is not possible to do
   correct auto-detection.
   [default: 60] [currently: 60]

option_context()

option_context上下文管理器用于在with语句中临时设置选项。当退出with块时,选项值会自动恢复。

display.max_rows

使用option_context(),我们可以临时设置值。

import pandas as pd
with pd.option_context("display.max_rows",10):
   print(pd.get_option("display.max_rows"))
   print(pd.get_option("display.max_rows"))

其 **输出** 如下:

10
10

请看第一个和第二个print语句的区别。第一个语句打印由option_context()设置的值,该值仅在with上下文中是临时的。在with上下文之后,第二个print语句打印配置的值。

常用参数

序号 参数和描述
1

display.max_rows

显示要显示的最大行数

2

2 display.max_columns

显示要显示的最大列数

3

display.expand_frame_repr

显示DataFrames以扩展页面

4

display.max_colwidth

显示最大列宽

5

display.precision

显示小数的精度

Python Pandas - 索引和数据选择

在本章中,我们将讨论如何切片和处理日期,以及如何一般地获取Pandas对象的子集。

Python和NumPy的索引运算符“[ ]”和属性运算符“.”为Pandas数据结构提供了快速简便的访问方式,适用于各种用例。但是,由于要访问的数据类型事先未知,因此直接使用标准运算符存在一些优化限制。对于生产代码,我们建议您利用本章中解释的优化的Pandas数据访问方法。

Pandas现在支持三种类型的多轴索引;三种类型在以下表格中提到:

序号 索引和描述
1

.loc()

基于标签

2

.iloc()

基于整数

3

.ix()

基于标签和整数

.loc()

Pandas提供各种方法来进行纯粹的基于标签的索引。在切片时,起始边界也包括在内。整数是有效的标签,但它们指的是标签而不是位置。

.loc()有多种访问方法,例如:

  • 单个标量标签
  • 标签列表
  • 切片对象
  • 布尔数组

loc接受两个用“,”分隔的单个/列表/范围运算符。第一个表示行,第二个表示列。

示例 1

#import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4),
index = ['a','b','c','d','e','f','g','h'], columns = ['A', 'B', 'C', 'D'])

#select all rows for a specific column
print df.loc[:,'A']

其 **输出** 如下:

a   0.391548
b  -0.070649
c  -0.317212
d  -2.162406
e   2.202797
f   0.613709
g   1.050559
h   1.122680
Name: A, dtype: float64

示例 2

# import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4),
index = ['a','b','c','d','e','f','g','h'], columns = ['A', 'B', 'C', 'D'])

# Select all rows for multiple columns, say list[]
print df.loc[:,['A','C']]

其 **输出** 如下:

            A           C
a    0.391548    0.745623
b   -0.070649    1.620406
c   -0.317212    1.448365
d   -2.162406   -0.873557
e    2.202797    0.528067
f    0.613709    0.286414
g    1.050559    0.216526
h    1.122680   -1.621420

示例3

# import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4),
index = ['a','b','c','d','e','f','g','h'], columns = ['A', 'B', 'C', 'D'])

# Select few rows for multiple columns, say list[]
print df.loc[['a','b','f','h'],['A','C']]

其 **输出** 如下:

           A          C
a   0.391548   0.745623
b  -0.070649   1.620406
f   0.613709   0.286414
h   1.122680  -1.621420

示例4

# import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4),
index = ['a','b','c','d','e','f','g','h'], columns = ['A', 'B', 'C', 'D'])

# Select range of rows for all columns
print df.loc['a':'h']

其 **输出** 如下:

            A           B          C          D
a    0.391548   -0.224297   0.745623   0.054301
b   -0.070649   -0.880130   1.620406   1.419743
c   -0.317212   -1.929698   1.448365   0.616899
d   -2.162406    0.614256  -0.873557   1.093958
e    2.202797   -2.315915   0.528067   0.612482
f    0.613709   -0.157674   0.286414  -0.500517
g    1.050559   -2.272099   0.216526   0.928449
h    1.122680    0.324368  -1.621420  -0.741470

示例5

# import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4),
index = ['a','b','c','d','e','f','g','h'], columns = ['A', 'B', 'C', 'D'])

# for getting values with a boolean array
print df.loc['a']>0

其 **输出** 如下:

A  False
B  True
C  False
D  False
Name: a, dtype: bool

.iloc()

Pandas提供各种方法来进行纯粹的基于整数的索引。像Python和NumPy一样,这些是基于0的索引。

各种访问方法如下:

  • 一个整数
  • 整数列表
  • 一系列值

示例 1

# import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

# select all rows for a specific column
print df.iloc[:4]

其 **输出** 如下:

           A          B           C           D
0   0.699435   0.256239   -1.270702   -0.645195
1  -0.685354   0.890791   -0.813012    0.631615
2  -0.783192  -0.531378    0.025070    0.230806
3   0.539042  -1.284314    0.826977   -0.026251

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

# Integer slicing
print df.iloc[:4]
print df.iloc[1:5, 2:4]

其 **输出** 如下:

           A          B           C           D
0   0.699435   0.256239   -1.270702   -0.645195
1  -0.685354   0.890791   -0.813012    0.631615
2  -0.783192  -0.531378    0.025070    0.230806
3   0.539042  -1.284314    0.826977   -0.026251

           C          D
1  -0.813012   0.631615
2   0.025070   0.230806
3   0.826977  -0.026251
4   1.423332   1.130568

示例3

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

# Slicing through list of values
print df.iloc[[1, 3, 5], [1, 3]]
print df.iloc[1:3, :]
print df.iloc[:,1:3]

其 **输出** 如下:

           B           D
1   0.890791    0.631615
3  -1.284314   -0.026251
5  -0.512888   -0.518930

           A           B           C           D
1  -0.685354    0.890791   -0.813012    0.631615
2  -0.783192   -0.531378    0.025070    0.230806

           B           C
0   0.256239   -1.270702
1   0.890791   -0.813012
2  -0.531378    0.025070
3  -1.284314    0.826977
4  -0.460729    1.423332
5  -0.512888    0.581409
6  -1.204853    0.098060
7  -0.947857    0.641358

.ix()

除了纯粹的基于标签和基于整数的索引外,Pandas还提供了一种混合方法,可以使用.ix()运算符选择和子集对象。

示例 1

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

# Integer slicing
print df.ix[:4]

其 **输出** 如下:

           A          B           C           D
0   0.699435   0.256239   -1.270702   -0.645195
1  -0.685354   0.890791   -0.813012    0.631615
2  -0.783192  -0.531378    0.025070    0.230806
3   0.539042  -1.284314    0.826977   -0.026251

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])
# Index slicing
print df.ix[:,'A']

其 **输出** 如下:

0   0.699435
1  -0.685354
2  -0.783192
3   0.539042
4  -1.044209
5  -1.415411
6   1.062095
7   0.994204
Name: A, dtype: float64

符号的使用

使用多轴索引从Pandas对象中获取值使用以下符号:

对象 索引器 返回类型
Series s.loc[indexer] 标量值
DataFrame df.loc[row_index,col_index] Series对象
Panel p.loc[item_index,major_index, minor_index] p.loc[item_index,major_index, minor_index]

注意 - .iloc() & .ix() 应用相同的索引选项和返回值。

现在让我们看看如何在DataFrame对象上执行每个操作。我们将使用基本的索引运算符“[ ]”

示例 1

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])
print df['A']

其 **输出** 如下:

0  -0.478893
1   0.391931
2   0.336825
3  -1.055102
4  -0.165218
5  -0.328641
6   0.567721
7  -0.759399
Name: A, dtype: float64

注意 - 我们可以将值列表传递给“[ ]”以选择这些列。

示例 2

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

print df[['A','B']]

其 **输出** 如下:

           A           B
0  -0.478893   -0.606311
1   0.391931   -0.949025
2   0.336825    0.093717
3  -1.055102   -0.012944
4  -0.165218    1.550310
5  -0.328641   -0.226363
6   0.567721   -0.312585
7  -0.759399   -0.372696

示例3

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])
print df[2:2]

其 **输出** 如下:

Columns: [A, B, C, D]
Index: []

属性访问

可以使用属性运算符“.”选择列。

示例

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

print df.A

其 **输出** 如下:

0   -0.478893
1    0.391931
2    0.336825
3   -1.055102
4   -0.165218
5   -0.328641
6    0.567721
7   -0.759399
Name: A, dtype: float64

Python Pandas - 统计函数

统计方法有助于理解和分析数据的行为。现在我们将学习一些统计函数,这些函数可以应用于Pandas对象。

百分比变化

Series、DataFrames和Panel都有函数pct_change()。此函数将每个元素与其之前的元素进行比较并计算变化百分比。

import pandas as pd
import numpy as np
s = pd.Series([1,2,3,4,5,4])
print s.pct_change()

df = pd.DataFrame(np.random.randn(5, 2))
print df.pct_change()

其 **输出** 如下:

0        NaN
1   1.000000
2   0.500000
3   0.333333
4   0.250000
5  -0.200000
dtype: float64

            0          1
0         NaN        NaN
1  -15.151902   0.174730
2  -0.746374   -1.449088
3  -3.582229   -3.165836
4   15.601150  -1.860434

默认情况下,pct_change()作用于列;如果要按行应用相同的操作,则使用axis=1()参数。

协方差

协方差应用于系列数据。Series对象有一个cov方法来计算系列对象之间的协方差。NA将自动排除。

Cov Series

import pandas as pd
import numpy as np
s1 = pd.Series(np.random.randn(10))
s2 = pd.Series(np.random.randn(10))
print s1.cov(s2)

其 **输出** 如下:

-0.12978405324

当协方差方法应用于DataFrame时,计算所有列之间的cov

import pandas as pd
import numpy as np
frame = pd.DataFrame(np.random.randn(10, 5), columns=['a', 'b', 'c', 'd', 'e'])
print frame['a'].cov(frame['b'])
print frame.cov()

其 **输出** 如下:

-0.58312921152741437

           a           b           c           d            e
a   1.780628   -0.583129   -0.185575    0.003679    -0.136558
b  -0.583129    1.297011    0.136530   -0.523719     0.251064
c  -0.185575    0.136530    0.915227   -0.053881    -0.058926
d   0.003679   -0.523719   -0.053881    1.521426    -0.487694
e  -0.136558    0.251064   -0.058926   -0.487694     0.960761

注意 - 观察第一个语句中ab列之间的cov,该值与DataFrame上的cov返回的值相同。

相关性

相关性显示任何两个值数组(序列)之间的线性关系。有多种方法可以计算相关性,例如pearson(默认)、spearman和kendall。

import pandas as pd
import numpy as np
frame = pd.DataFrame(np.random.randn(10, 5), columns=['a', 'b', 'c', 'd', 'e'])

print frame['a'].corr(frame['b'])
print frame.corr()

其 **输出** 如下:

-0.383712785514

           a          b          c          d           e
a   1.000000  -0.383713  -0.145368   0.002235   -0.104405
b  -0.383713   1.000000   0.125311  -0.372821    0.224908
c  -0.145368   0.125311   1.000000  -0.045661   -0.062840
d   0.002235  -0.372821  -0.045661   1.000000   -0.403380
e  -0.104405   0.224908  -0.062840  -0.403380    1.000000

如果DataFrame中存在任何非数字列,则会自动将其排除。

数据排名

数据排名为元素数组中的每个元素生成排名。如果出现平局,则分配平均排名。

import pandas as pd
import numpy as np

s = pd.Series(np.random.np.random.randn(5), index=list('abcde'))
s['d'] = s['b'] # so there's a tie
print s.rank()

其 **输出** 如下:

a  1.0
b  3.5
c  2.0
d  3.5
e  5.0
dtype: float64

Rank可选地接受一个ascending参数,默认为true;当为false时,数据被反向排名,较大的值被赋予较小的排名。

Rank支持不同的平局分解方法,由method参数指定:

  • average - 平局组的平均排名

  • min - 组中的最低排名

  • max - 组中的最高排名

  • first - 按数组中出现的顺序分配排名

Python Pandas - 窗口函数

对于数值数据,Pandas提供了一些变体,例如滚动、扩展和指数移动权重,用于窗口统计。其中包括sum、mean、median、variance、covariance、correlation等。

现在我们将学习如何在DataFrame对象上应用这些方法。

.rolling() 函数

此函数可以应用于一系列数据。指定window=n参数,并在其上应用适当的统计函数。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df.rolling(window=3).mean()

其 **输出** 如下:

                    A           B           C           D
2000-01-01        NaN         NaN         NaN         NaN
2000-01-02        NaN         NaN         NaN         NaN
2000-01-03   0.434553   -0.667940   -1.051718   -0.826452
2000-01-04   0.628267   -0.047040   -0.287467   -0.161110
2000-01-05   0.398233    0.003517    0.099126   -0.405565
2000-01-06   0.641798    0.656184   -0.322728    0.428015
2000-01-07   0.188403    0.010913   -0.708645    0.160932
2000-01-08   0.188043   -0.253039   -0.818125   -0.108485
2000-01-09   0.682819   -0.606846   -0.178411   -0.404127
2000-01-10   0.688583    0.127786    0.513832   -1.067156

注意 - 由于窗口大小为3,因此对于前两个元素存在空值,从第三个元素开始,其值为nn-1n-2元素的平均值。因此,我们也可以应用上面提到的各种函数。

.expanding() 函数

此函数可以应用于一系列数据。指定min_periods=n参数,并在其上应用适当的统计函数。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df.expanding(min_periods=3).mean()

其 **输出** 如下:

                   A           B           C           D
2000-01-01        NaN         NaN         NaN         NaN
2000-01-02        NaN         NaN         NaN         NaN
2000-01-03   0.434553   -0.667940   -1.051718   -0.826452
2000-01-04   0.743328   -0.198015   -0.852462   -0.262547
2000-01-05   0.614776   -0.205649   -0.583641   -0.303254
2000-01-06   0.538175   -0.005878   -0.687223   -0.199219
2000-01-07   0.505503   -0.108475   -0.790826   -0.081056
2000-01-08   0.454751   -0.223420   -0.671572   -0.230215
2000-01-09   0.586390   -0.206201   -0.517619   -0.267521
2000-01-10   0.560427   -0.037597   -0.399429   -0.376886

.ewm() 函数

ewm应用于一系列数据。指定com、span、halflife参数中的任何一个,并在其上应用适当的统计函数。它以指数方式分配权重。

import pandas as pd
import numpy as np
 
df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df.ewm(com=0.5).mean()

其 **输出** 如下:

                    A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   0.865131   -0.453626   -1.137961    0.058747
2000-01-03  -0.132245   -0.807671   -0.308308   -1.491002
2000-01-04   1.084036    0.555444   -0.272119    0.480111
2000-01-05   0.425682    0.025511    0.239162   -0.153290
2000-01-06   0.245094    0.671373   -0.725025    0.163310
2000-01-07   0.288030   -0.259337   -1.183515    0.473191
2000-01-08   0.162317   -0.771884   -0.285564   -0.692001
2000-01-09   1.147156   -0.302900    0.380851   -0.607976
2000-01-10   0.600216    0.885614    0.569808   -1.110113

窗口函数主要用于通过平滑曲线来图形化地查找数据中的趋势。如果日常数据变化很大并且有很多数据点可用,那么抽样和绘图是一种方法,应用窗口计算并在结果上绘制图形是另一种方法。通过这些方法,我们可以平滑曲线或趋势。

Python Pandas - 聚合

创建滚动、扩展和ewm对象后,可以使用多种方法对数据进行聚合。

在DataFrame上应用聚合

让我们创建一个DataFrame并在其上应用聚合。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])

print df
r = df.rolling(window=3,min_periods=1)
print r

其 **输出** 如下:

                    A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   0.790670   -0.387854   -0.668132    0.267283
2000-01-03  -0.575523   -0.965025    0.060427   -2.179780
2000-01-04   1.669653    1.211759   -0.254695    1.429166
2000-01-05   0.100568   -0.236184    0.491646   -0.466081
2000-01-06   0.155172    0.992975   -1.205134    0.320958
2000-01-07   0.309468   -0.724053   -1.412446    0.627919
2000-01-08   0.099489   -1.028040    0.163206   -1.274331
2000-01-09   1.639500   -0.068443    0.714008   -0.565969
2000-01-10   0.326761    1.479841    0.664282   -1.361169

Rolling [window=3,min_periods=1,center=False,axis=0]                

我们可以通过将函数传递给整个DataFrame来进行聚合,或者通过标准的get item方法选择一列。

在整个DataFrame上应用聚合

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df
r = df.rolling(window=3,min_periods=1)
print r.aggregate(np.sum)

其 **输出** 如下:

                    A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   1.879182   -1.038796   -3.215581   -0.299575
2000-01-03   1.303660   -2.003821   -3.155154   -2.479355
2000-01-04   1.884801   -0.141119   -0.862400   -0.483331
2000-01-05   1.194699    0.010551    0.297378   -1.216695
2000-01-06   1.925393    1.968551   -0.968183    1.284044
2000-01-07   0.565208    0.032738   -2.125934    0.482797
2000-01-08   0.564129   -0.759118   -2.454374   -0.325454
2000-01-09   2.048458   -1.820537   -0.535232   -1.212381
2000-01-10   2.065750    0.383357    1.541496   -3.201469

                    A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   1.879182   -1.038796   -3.215581   -0.299575
2000-01-03   1.303660   -2.003821   -3.155154   -2.479355
2000-01-04   1.884801   -0.141119   -0.862400   -0.483331
2000-01-05   1.194699    0.010551    0.297378   -1.216695
2000-01-06   1.925393    1.968551   -0.968183    1.284044
2000-01-07   0.565208    0.032738   -2.125934    0.482797
2000-01-08   0.564129   -0.759118   -2.454374   -0.325454
2000-01-09   2.048458   -1.820537   -0.535232   -1.212381
2000-01-10   2.065750    0.383357    1.541496   -3.201469

在DataFrame的单个列上应用聚合

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df
r = df.rolling(window=3,min_periods=1)
print r['A'].aggregate(np.sum)

其 **输出** 如下:

                 A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   1.879182   -1.038796   -3.215581   -0.299575
2000-01-03   1.303660   -2.003821   -3.155154   -2.479355
2000-01-04   1.884801   -0.141119   -0.862400   -0.483331
2000-01-05   1.194699    0.010551    0.297378   -1.216695
2000-01-06   1.925393    1.968551   -0.968183    1.284044
2000-01-07   0.565208    0.032738   -2.125934    0.482797
2000-01-08   0.564129   -0.759118   -2.454374   -0.325454
2000-01-09   2.048458   -1.820537   -0.535232   -1.212381
2000-01-10   2.065750    0.383357    1.541496   -3.201469
2000-01-01   1.088512
2000-01-02   1.879182
2000-01-03   1.303660
2000-01-04   1.884801
2000-01-05   1.194699
2000-01-06   1.925393
2000-01-07   0.565208
2000-01-08   0.564129
2000-01-09   2.048458
2000-01-10   2.065750
Freq: D, Name: A, dtype: float64

在DataFrame的多个列上应用聚合

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df
r = df.rolling(window=3,min_periods=1)
print r[['A','B']].aggregate(np.sum)

其 **输出** 如下:

                 A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   1.879182   -1.038796   -3.215581   -0.299575
2000-01-03   1.303660   -2.003821   -3.155154   -2.479355
2000-01-04   1.884801   -0.141119   -0.862400   -0.483331
2000-01-05   1.194699    0.010551    0.297378   -1.216695
2000-01-06   1.925393    1.968551   -0.968183    1.284044
2000-01-07   0.565208    0.032738   -2.125934    0.482797
2000-01-08   0.564129   -0.759118   -2.454374   -0.325454
2000-01-09   2.048458   -1.820537   -0.535232   -1.212381
2000-01-10   2.065750    0.383357    1.541496   -3.201469
                    A           B
2000-01-01   1.088512   -0.650942
2000-01-02   1.879182   -1.038796
2000-01-03   1.303660   -2.003821
2000-01-04   1.884801   -0.141119
2000-01-05   1.194699    0.010551
2000-01-06   1.925393    1.968551
2000-01-07   0.565208    0.032738
2000-01-08   0.564129   -0.759118
2000-01-09   2.048458   -1.820537
2000-01-10   2.065750    0.383357

在DataFrame的单个列上应用多个函数

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df
r = df.rolling(window=3,min_periods=1)
print r['A'].aggregate([np.sum,np.mean])

其 **输出** 如下:

                 A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   1.879182   -1.038796   -3.215581   -0.299575
2000-01-03   1.303660   -2.003821   -3.155154   -2.479355
2000-01-04   1.884801   -0.141119   -0.862400   -0.483331
2000-01-05   1.194699    0.010551    0.297378   -1.216695
2000-01-06   1.925393    1.968551   -0.968183    1.284044
2000-01-07   0.565208    0.032738   -2.125934    0.482797
2000-01-08   0.564129   -0.759118   -2.454374   -0.325454
2000-01-09   2.048458   -1.820537   -0.535232   -1.212381
2000-01-10   2.065750    0.383357    1.541496   -3.201469
                  sum       mean
2000-01-01   1.088512   1.088512
2000-01-02   1.879182   0.939591
2000-01-03   1.303660   0.434553
2000-01-04   1.884801   0.628267
2000-01-05   1.194699   0.398233
2000-01-06   1.925393   0.641798
2000-01-07   0.565208   0.188403
2000-01-08   0.564129   0.188043
2000-01-09   2.048458   0.682819
2000-01-10   2.065750   0.688583

在DataFrame的多个列上应用多个函数

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df
r = df.rolling(window=3,min_periods=1)
print r[['A','B']].aggregate([np.sum,np.mean])

其 **输出** 如下:

                 A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   1.879182   -1.038796   -3.215581   -0.299575
2000-01-03   1.303660   -2.003821   -3.155154   -2.479355
2000-01-04   1.884801   -0.141119   -0.862400   -0.483331
2000-01-05   1.194699    0.010551    0.297378   -1.216695
2000-01-06   1.925393    1.968551   -0.968183    1.284044
2000-01-07   0.565208    0.032738   -2.125934    0.482797
2000-01-08   0.564129   -0.759118   -2.454374   -0.325454
2000-01-09   2.048458   -1.820537   -0.535232   -1.212381
2000-01-10   2.065750    0.383357    1.541496   -3.201469
                    A                      B
                  sum       mean         sum        mean
2000-01-01   1.088512   1.088512   -0.650942   -0.650942
2000-01-02   1.879182   0.939591   -1.038796   -0.519398
2000-01-03   1.303660   0.434553   -2.003821   -0.667940
2000-01-04   1.884801   0.628267   -0.141119   -0.047040
2000-01-05   1.194699   0.398233    0.010551    0.003517
2000-01-06   1.925393   0.641798    1.968551    0.656184
2000-01-07   0.565208   0.188403    0.032738    0.010913
2000-01-08   0.564129   0.188043   -0.759118   -0.253039
2000-01-09   2.048458   0.682819   -1.820537   -0.606846
2000-01-10   2.065750   0.688583    0.383357    0.127786

将不同的函数应用于DataFrame的不同列

import pandas as pd
import numpy as np
 
df = pd.DataFrame(np.random.randn(3, 4),
   index = pd.date_range('1/1/2000', periods=3),
   columns = ['A', 'B', 'C', 'D'])
print df
r = df.rolling(window=3,min_periods=1)
print r.aggregate({'A' : np.sum,'B' : np.mean})

其 **输出** 如下:

                    A          B          C         D
2000-01-01  -1.575749  -1.018105   0.317797  0.545081
2000-01-02  -0.164917  -1.361068   0.258240  1.113091
2000-01-03   1.258111   1.037941  -0.047487  0.867371
                    A          B
2000-01-01  -1.575749  -1.018105
2000-01-02  -1.740666  -1.189587
2000-01-03  -0.482555  -0.447078

Python Pandas - 缺失数据

缺失数据在现实场景中始终是一个问题。机器学习和数据挖掘等领域由于数据质量差(由缺失值引起),其模型预测的准确性面临严重问题。在这些领域,缺失值处理是提高模型准确性和有效性的一个主要关注点。

数据何时以及为何缺失?

让我们考虑一个产品的在线调查。很多时候,人们不会分享与他们相关的所有信息。一些人分享他们的体验,但没有分享他们使用产品的时间长短;一些人分享他们使用产品的时间长短和他们的体验,但没有分享他们的联系方式。因此,以某种方式,数据的一部分总是缺失的,这在实时数据中非常常见。

现在让我们看看如何使用Pandas处理缺失值(例如NA或NaN)。

# import the pandas library
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

print df

其 **输出** 如下:

         one        two      three
a   0.077988   0.476149   0.965836
b        NaN        NaN        NaN
c  -0.390208  -0.551605  -2.301950
d        NaN        NaN        NaN
e  -2.000303  -0.788201   1.510072
f  -0.930230  -0.670473   1.146615
g        NaN        NaN        NaN
h   0.085100   0.532791   0.887415

使用重新索引,我们创建了一个包含缺失值的DataFrame。在输出中,NaN 表示非数字

检查缺失值

为了更容易地检测缺失值(并跨越不同的数组数据类型),Pandas提供了isnull()notnull()函数,它们也是Series和DataFrame对象的的方法−

示例 1

import pandas as pd
import numpy as np
 
df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

print df['one'].isnull()

其 **输出** 如下:

a  False
b  True
c  False
d  True
e  False
f  False
g  True
h  False
Name: one, dtype: bool

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

print df['one'].notnull()

其 **输出** 如下:

a  True
b  False
c  True
d  False
e  True
f  True
g  False
h  True
Name: one, dtype: bool

缺失数据的计算

  • 在对数据求和时,NA将被视为零。
  • 如果数据全是NA,则结果将为NA。

示例 1

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

print df['one'].sum()

其 **输出** 如下:

2.02357685917

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(index=[0,1,2,3,4,5],columns=['one','two'])
print df['one'].sum()

其 **输出** 如下:

nan

清理/填充缺失数据

Pandas提供了多种清理缺失值的方法。fillna函数可以通过几种方式用非空数据“填充”NA值,我们在以下章节中进行了说明。

用标量值替换NaN

以下程序显示了如何用“0”替换“NaN”。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(3, 3), index=['a', 'c', 'e'],columns=['one',
'two', 'three'])

df = df.reindex(['a', 'b', 'c'])

print df
print ("NaN replaced with '0':")
print df.fillna(0)

其 **输出** 如下:

         one        two     three
a  -0.576991  -0.741695  0.553172
b        NaN        NaN       NaN
c   0.744328  -1.735166  1.749580

NaN replaced with '0':
         one        two     three
a  -0.576991  -0.741695  0.553172
b   0.000000   0.000000  0.000000
c   0.744328  -1.735166  1.749580

这里,我们用零填充;我们也可以用任何其他值填充。

向前和向后填充NA

使用重新索引章节中讨论的填充概念,我们将填充缺失值。

序号 方法和操作
1

pad/fill

向前填充方法

2

bfill/backfill

向后填充方法

示例 1

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

print df.fillna(method='pad')

其 **输出** 如下:

         one        two      three
a   0.077988   0.476149   0.965836
b   0.077988   0.476149   0.965836
c  -0.390208  -0.551605  -2.301950
d  -0.390208  -0.551605  -2.301950
e  -2.000303  -0.788201   1.510072
f  -0.930230  -0.670473   1.146615
g  -0.930230  -0.670473   1.146615
h   0.085100   0.532791   0.887415

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

print df.fillna(method='backfill')

其 **输出** 如下:

         one        two      three
a   0.077988   0.476149   0.965836
b  -0.390208  -0.551605  -2.301950
c  -0.390208  -0.551605  -2.301950
d  -2.000303  -0.788201   1.510072
e  -2.000303  -0.788201   1.510072
f  -0.930230  -0.670473   1.146615
g   0.085100   0.532791   0.887415
h   0.085100   0.532791   0.887415

删除缺失值

如果只想排除缺失值,则使用dropna函数以及axis参数。默认情况下,axis=0,即沿行,这意味着如果一行中的任何值都是NA,则整行都将被排除。

示例 1

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print df.dropna()

其 **输出** 如下:

         one        two      three
a   0.077988   0.476149   0.965836
c  -0.390208  -0.551605  -2.301950
e  -2.000303  -0.788201   1.510072
f  -0.930230  -0.670473   1.146615
h   0.085100   0.532791   0.887415

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f',
'h'],columns=['one', 'two', 'three'])

df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print df.dropna(axis=1)

其 **输出** 如下:

Empty DataFrame
Columns: [ ]
Index: [a, b, c, d, e, f, g, h]

替换缺失值(或)通用值

很多时候,我们必须用某个特定值替换通用值。我们可以通过应用replace方法来实现这一点。

用标量值替换NA等同于fillna()函数的行为。

示例 1

import pandas as pd
import numpy as np

df = pd.DataFrame({'one':[10,20,30,40,50,2000], 'two':[1000,0,30,40,50,60]})

print df.replace({1000:10,2000:60})

其 **输出** 如下:

   one  two
0   10   10
1   20    0
2   30   30
3   40   40
4   50   50
5   60   60

示例 2

import pandas as pd
import numpy as np

df = pd.DataFrame({'one':[10,20,30,40,50,2000], 'two':[1000,0,30,40,50,60]})
print df.replace({1000:10,2000:60})

其 **输出** 如下:

   one  two
0   10   10
1   20    0
2   30   30
3   40   40
4   50   50
5   60   60

Python Pandas - GroupBy

任何groupby操作都涉及对原始对象执行以下操作之一。它们是−

  • 拆分对象

  • 应用函数

  • 组合结果

在许多情况下,我们将数据拆分成多个集合,并在每个子集上应用一些功能。在应用功能中,我们可以执行以下操作−

  • 聚合−计算汇总统计数据

  • 转换−执行一些特定于组的操作

  • 过滤−根据某些条件丢弃数据

现在让我们创建一个DataFrame对象,并在其上执行所有操作−

#import the pandas library
import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

print df

其 **输出** 如下:

    Points   Rank     Team   Year
0      876      1   Riders   2014
1      789      2   Riders   2015
2      863      2   Devils   2014
3      673      3   Devils   2015
4      741      3    Kings   2014
5      812      4    kings   2015
6      756      1    Kings   2016
7      788      1    Kings   2017
8      694      2   Riders   2016
9      701      4   Royals   2014
10     804      1   Royals   2015
11     690      2   Riders   2017

将数据分成组

Pandas对象可以拆分成任何其对象。有多种方法可以拆分对象,例如−

  • obj.groupby('key')
  • obj.groupby(['key1','key2'])
  • obj.groupby(key,axis=1)

现在让我们看看如何将分组对象应用于DataFrame对象。

示例

# import the pandas library
import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

print df.groupby('Team')

其 **输出** 如下:

<pandas.core.groupby.DataFrameGroupBy object at 0x7fa46a977e50>

查看组

# import the pandas library
import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

print df.groupby('Team').groups

其 **输出** 如下:

{'Kings': Int64Index([4, 6, 7],      dtype='int64'),
'Devils': Int64Index([2, 3],         dtype='int64'),
'Riders': Int64Index([0, 1, 8, 11],  dtype='int64'),
'Royals': Int64Index([9, 10],        dtype='int64'),
'kings' : Int64Index([5],            dtype='int64')}

示例

分组包含多个列−

# import the pandas library
import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

print df.groupby(['Team','Year']).groups

其 **输出** 如下:

{('Kings', 2014): Int64Index([4], dtype='int64'),
 ('Royals', 2014): Int64Index([9], dtype='int64'),
 ('Riders', 2014): Int64Index([0], dtype='int64'),
 ('Riders', 2015): Int64Index([1], dtype='int64'),
 ('Kings', 2016): Int64Index([6], dtype='int64'),
 ('Riders', 2016): Int64Index([8], dtype='int64'),
 ('Riders', 2017): Int64Index([11], dtype='int64'),
 ('Devils', 2014): Int64Index([2], dtype='int64'),
 ('Devils', 2015): Int64Index([3], dtype='int64'),
 ('kings', 2015): Int64Index([5], dtype='int64'),
 ('Royals', 2015): Int64Index([10], dtype='int64'),
 ('Kings', 2017): Int64Index([7], dtype='int64')}

迭代组

有了groupby对象,我们可以像itertools.obj一样迭代该对象。

# import the pandas library
import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

grouped = df.groupby('Year')

for name,group in grouped:
   print name
   print group

其 **输出** 如下:

2014
   Points  Rank     Team   Year
0     876     1   Riders   2014
2     863     2   Devils   2014
4     741     3   Kings    2014
9     701     4   Royals   2014

2015
   Points  Rank     Team   Year
1     789     2   Riders   2015
3     673     3   Devils   2015
5     812     4    kings   2015
10    804     1   Royals   2015

2016
   Points  Rank     Team   Year
6     756     1    Kings   2016
8     694     2   Riders   2016

2017
   Points  Rank    Team   Year
7     788     1   Kings   2017
11    690     2  Riders   2017

默认情况下,groupby对象的标签名称与组名称相同。

选择一个组

使用get_group()方法,我们可以选择单个组。

# import the pandas library
import pandas as pd

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

grouped = df.groupby('Year')
print grouped.get_group(2014)

其 **输出** 如下:

   Points  Rank     Team    Year
0     876     1   Riders    2014
2     863     2   Devils    2014
4     741     3   Kings     2014
9     701     4   Royals    2014

聚合

聚合函数为每个组返回单个聚合值。创建group by对象后,可以对分组数据执行多个聚合操作。

一个明显的方法是通过aggregate或等效的agg方法进行聚合−

# import the pandas library
import pandas as pd
import numpy as np

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

grouped = df.groupby('Year')
print grouped['Points'].agg(np.mean)

其 **输出** 如下:

Year
2014   795.25
2015   769.50
2016   725.00
2017   739.00
Name: Points, dtype: float64

另一种查看每个组大小的方法是应用size()函数−

import pandas as pd
import numpy as np

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

Attribute Access in Python Pandas
grouped = df.groupby('Team')
print grouped.agg(np.size)

其 **输出** 如下:

         Points   Rank   Year
Team
Devils        2      2      2
Kings         3      3      3
Riders        4      4      4
Royals        2      2      2
kings         1      1      1

一次应用多个聚合函数

对于分组后的Series,您还可以传递一个函数列表函数字典来进行聚合,并生成DataFrame作为输出−

# import the pandas library
import pandas as pd
import numpy as np

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

grouped = df.groupby('Team')
print grouped['Points'].agg([np.sum, np.mean, np.std])

其 **输出** 如下:

Team      sum      mean          std
Devils   1536   768.000000   134.350288
Kings    2285   761.666667    24.006943
Riders   3049   762.250000    88.567771
Royals   1505   752.500000    72.831998
kings     812   812.000000          NaN

转换

对组或列的转换返回一个与被分组对象大小相同的对象。因此,转换应该返回与组块大小相同的结果。

# import the pandas library
import pandas as pd
import numpy as np

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

grouped = df.groupby('Team')
score = lambda x: (x - x.mean()) / x.std()*10
print grouped.transform(score)

其 **输出** 如下:

       Points        Rank        Year
0   12.843272  -15.000000  -11.618950
1   3.020286     5.000000   -3.872983
2   7.071068    -7.071068   -7.071068
3  -7.071068     7.071068    7.071068
4  -8.608621    11.547005  -10.910895
5        NaN          NaN         NaN
6  -2.360428    -5.773503    2.182179
7  10.969049    -5.773503    8.728716
8  -7.705963     5.000000    3.872983
9  -7.071068     7.071068   -7.071068
10  7.071068    -7.071068    7.071068
11 -8.157595     5.000000   11.618950

过滤

过滤根据定义的条件过滤数据并返回数据的子集。filter()函数用于过滤数据。

import pandas as pd
import numpy as np

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
   'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)

print df.groupby('Team').filter(lambda x: len(x) >= 3)

其 **输出** 如下:

    Points  Rank     Team   Year
0      876     1   Riders   2014
1      789     2   Riders   2015
4      741     3   Kings    2014
6      756     1   Kings    2016
7      788     1   Kings    2017
8      694     2   Riders   2016
11     690     2   Riders   2017

在上面的过滤条件中,我们要求返回在IPL中参赛三次或三次以上的队伍。

Python Pandas - 合并/连接

Pandas具有功能齐全、高性能的内存内连接操作,其用法与SQL等关系数据库非常相似。

Pandas提供了一个单一函数merge,作为DataFrame对象之间所有标准数据库连接操作的入口点−

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=True)

这里,我们使用了以下参数−

  • left − 一个DataFrame对象。

  • right − 另一个DataFrame对象。

  • on − 要连接的列(名称)。必须在左和右DataFrame对象中找到。

  • left_on − 从左DataFrame中用作键的列。可以是列名,也可以是长度等于DataFrame长度的数组。

  • right_on − 从右DataFrame中用作键的列。可以是列名,也可以是长度等于DataFrame长度的数组。

  • left_index − 如果为True,则使用左DataFrame的索引(行标签)作为其连接键。对于具有多索引(分层)的DataFrame,级别数必须与右DataFrame的连接键数匹配。

  • right_index − 与右DataFrame的left_index用法相同。

  • how − 'left'、'right'、'outer'、'inner'之一。默认为inner。每种方法都已在下面描述。

  • sort − 按字典顺序对结果DataFrame进行排序。默认为True,设置为False在许多情况下会大大提高性能。

现在让我们创建两个不同的DataFrame,并在其上执行合并操作。

# import the pandas library
import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame(
   {'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print left
print right

其 **输出** 如下:

    Name  id   subject_id
0   Alex   1         sub1
1    Amy   2         sub2
2  Allen   3         sub4
3  Alice   4         sub6
4  Ayoung  5         sub5

    Name  id   subject_id
0  Billy   1         sub2
1  Brian   2         sub4
2  Bran    3         sub3
3  Bryce   4         sub6
4  Betty   5         sub5

根据键合并两个DataFrame

import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame({
	'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print pd.merge(left,right,on='id')

其 **输出** 如下:

   Name_x   id  subject_id_x   Name_y   subject_id_y
0  Alex      1          sub1    Billy           sub2
1  Amy       2          sub2    Brian           sub4
2  Allen     3          sub4     Bran           sub3
3  Alice     4          sub6    Bryce           sub6
4  Ayoung    5          sub5    Betty           sub5

根据多个键合并两个DataFrame

import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame({
	'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print pd.merge(left,right,on=['id','subject_id'])

其 **输出** 如下:

    Name_x   id   subject_id   Name_y
0    Alice    4         sub6    Bryce
1   Ayoung    5         sub5    Betty

使用'how'参数合并

how参数用于合并,指定如何确定结果表中要包含哪些键。如果键组合不出现在左表或右表中,则连接表中的值将为NA。

以下是how选项及其SQL等效名称的摘要−

合并方法 SQL等效项 描述
left LEFT OUTER JOIN 使用左对象的键
right RIGHT OUTER JOIN 使用右对象的键
outer FULL OUTER JOIN 使用键的并集
inner INNER JOIN 使用键的交集

左连接

import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print pd.merge(left, right, on='subject_id', how='left')

其 **输出** 如下:

    Name_x   id_x   subject_id   Name_y   id_y
0     Alex      1         sub1      NaN    NaN
1      Amy      2         sub2    Billy    1.0
2    Allen      3         sub4    Brian    2.0
3    Alice      4         sub6    Bryce    4.0
4   Ayoung      5         sub5    Betty    5.0

右连接

import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print pd.merge(left, right, on='subject_id', how='right')

其 **输出** 如下:

    Name_x  id_x   subject_id   Name_y   id_y
0      Amy   2.0         sub2    Billy      1
1    Allen   3.0         sub4    Brian      2
2    Alice   4.0         sub6    Bryce      4
3   Ayoung   5.0         sub5    Betty      5
4      NaN   NaN         sub3     Bran      3

外连接

import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print pd.merge(left, right, how='outer', on='subject_id')

其 **输出** 如下:

    Name_x  id_x   subject_id   Name_y   id_y
0     Alex   1.0         sub1      NaN    NaN
1      Amy   2.0         sub2    Billy    1.0
2    Allen   3.0         sub4    Brian    2.0
3    Alice   4.0         sub6    Bryce    4.0
4   Ayoung   5.0         sub5    Betty    5.0
5      NaN   NaN         sub3     Bran    3.0

内连接

连接将在索引上执行。连接操作尊重在其上调用的对象。因此,a.join(b)不等于b.join(a)

import pandas as pd
left = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5']})
right = pd.DataFrame({
   'id':[1,2,3,4,5],
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5']})
print pd.merge(left, right, on='subject_id', how='inner')

其 **输出** 如下:

    Name_x   id_x   subject_id   Name_y   id_y
0      Amy      2         sub2    Billy      1
1    Allen      3         sub4    Brian      2
2    Alice      4         sub6    Bryce      4
3   Ayoung      5         sub5    Betty      5

Python Pandas - 级联

Pandas提供了各种工具,可以轻松地将Series、DataFramePanel对象组合在一起。

 pd.concat(objs,axis=0,join='outer',join_axes=None,
ignore_index=False)
  • objs − 这是Series、DataFrame或Panel对象的序列或映射。

  • axis − {0, 1, ...},默认为0。这是要沿其连接的轴。

  • join − {‘inner’, ‘outer’},默认为‘outer’。如何处理其他轴上的索引。外部用于联合,内部用于交集。

  • ignore_index − 布尔值,默认为False。如果为True,则不使用连接轴上的索引值。结果轴将标记为0、...、n - 1。

  • join_axes − 这是Index对象的列表。要使用的特定索引用于其他(n-1)轴,而不是执行内部/外部集合逻辑。

连接对象

concat函数完成了沿轴执行连接操作的所有繁重工作。让我们创建不同的对象并进行连接。

import pandas as pd

one = pd.DataFrame({
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5'],
   'Marks_scored':[98,90,87,69,78]},
   index=[1,2,3,4,5])

two = pd.DataFrame({
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5'],
   'Marks_scored':[89,80,79,97,88]},
   index=[1,2,3,4,5])
print pd.concat([one,two])

其 **输出** 如下:

    Marks_scored     Name   subject_id
1             98     Alex         sub1
2             90      Amy         sub2
3             87    Allen         sub4
4             69    Alice         sub6
5             78   Ayoung         sub5
1             89    Billy         sub2
2             80    Brian         sub4
3             79     Bran         sub3
4             97    Bryce         sub6
5             88    Betty         sub5

假设我们想将特定的键与分割的DataFrame的每个部分关联。我们可以使用keys参数来做到这一点−

import pandas as pd

one = pd.DataFrame({
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5'],
   'Marks_scored':[98,90,87,69,78]},
   index=[1,2,3,4,5])

two = pd.DataFrame({
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5'],
   'Marks_scored':[89,80,79,97,88]},
   index=[1,2,3,4,5])
print pd.concat([one,two],keys=['x','y'])

其 **输出** 如下:

x  1  98    Alex    sub1
   2  90    Amy     sub2
   3  87    Allen   sub4
   4  69    Alice   sub6
   5  78    Ayoung  sub5
y  1  89    Billy   sub2
   2  80    Brian   sub4
   3  79    Bran    sub3
   4  97    Bryce   sub6
   5  88    Betty   sub5

结果的索引是重复的;每个索引都重复。

如果结果对象必须遵循其自身的索引,则将ignore_index设置为True

import pandas as pd

one = pd.DataFrame({
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5'],
   'Marks_scored':[98,90,87,69,78]},
   index=[1,2,3,4,5])

two = pd.DataFrame({
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5'],
   'Marks_scored':[89,80,79,97,88]},
   index=[1,2,3,4,5])
print pd.concat([one,two],keys=['x','y'],ignore_index=True)

其 **输出** 如下:

    Marks_scored     Name    subject_id
0             98     Alex          sub1
1             90      Amy          sub2
2             87    Allen          sub4
3             69    Alice          sub6
4             78   Ayoung          sub5
5             89    Billy          sub2
6             80    Brian          sub4
7             79     Bran          sub3
8             97    Bryce          sub6
9             88    Betty          sub5

观察,索引完全改变了,键也被覆盖了。

如果需要沿axis=1添加两个对象,则将追加新列。

import pandas as pd

one = pd.DataFrame({
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5'],
   'Marks_scored':[98,90,87,69,78]},
   index=[1,2,3,4,5])

two = pd.DataFrame({
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5'],
   'Marks_scored':[89,80,79,97,88]},
   index=[1,2,3,4,5])
print pd.concat([one,two],axis=1)

其 **输出** 如下:

    Marks_scored    Name  subject_id   Marks_scored    Name   subject_id
1           98      Alex      sub1         89         Billy         sub2
2           90       Amy      sub2         80         Brian         sub4
3           87     Allen      sub4         79          Bran         sub3
4           69     Alice      sub6         97         Bryce         sub6
5           78    Ayoung      sub5         88         Betty         sub5

使用append连接

concat的一个有用的快捷方式是Series和DataFrame上的append实例方法。这些方法实际上早于concat。它们沿axis=0连接,即索引−

import pandas as pd

one = pd.DataFrame({
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5'],
   'Marks_scored':[98,90,87,69,78]},
   index=[1,2,3,4,5])

two = pd.DataFrame({
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5'],
   'Marks_scored':[89,80,79,97,88]},
   index=[1,2,3,4,5])
print one.append(two)

其 **输出** 如下:

    Marks_scored    Name  subject_id
1           98      Alex      sub1
2           90       Amy      sub2
3           87     Allen      sub4
4           69     Alice      sub6
5           78    Ayoung      sub5
1           89     Billy      sub2
2           80     Brian      sub4
3           79      Bran      sub3
4           97     Bryce      sub6
5           88     Betty      sub5

append函数也可以接受多个对象−

import pandas as pd

one = pd.DataFrame({
   'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
   'subject_id':['sub1','sub2','sub4','sub6','sub5'],
   'Marks_scored':[98,90,87,69,78]},
   index=[1,2,3,4,5])

two = pd.DataFrame({
   'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
   'subject_id':['sub2','sub4','sub3','sub6','sub5'],
   'Marks_scored':[89,80,79,97,88]},
   index=[1,2,3,4,5])
print one.append([two,one,two])

其 **输出** 如下:

    Marks_scored   Name    subject_id
1           98     Alex          sub1
2           90      Amy          sub2
3           87    Allen          sub4
4           69    Alice          sub6
5           78   Ayoung          sub5
1           89    Billy          sub2
2           80    Brian          sub4
3           79     Bran          sub3
4           97    Bryce          sub6
5           88    Betty          sub5
1           98     Alex          sub1
2           90      Amy          sub2
3           87    Allen          sub4
4           69    Alice          sub6
5           78   Ayoung          sub5
1           89    Billy          sub2
2           80    Brian          sub4
3           79     Bran          sub3
4           97    Bryce          sub6
5           88    Betty          sub5

时间序列

Pandas提供了一个强大的工具来处理时间序列数据,尤其是在金融领域。处理时间序列数据时,我们经常遇到以下情况−

  • 生成时间序列
  • 将时间序列转换为不同的频率

Pandas提供了一套相对紧凑且独立的工具来执行上述任务。

获取当前时间

datetime.now()提供当前日期和时间。

import pandas as pd

print pd.datetime.now()

其 **输出** 如下:

2017-05-11 06:10:13.393147

创建时间戳

带时间戳的数据是最基本的时间序列数据类型,它将值与时间点相关联。对于pandas对象,这意味着使用时间点。让我们举个例子−

import pandas as pd

print pd.Timestamp('2017-03-01')

其 **输出** 如下:

2017-03-01 00:00:00

也可以转换整数或浮点纪元时间。这些的默认单位是纳秒(因为这就是时间戳的存储方式)。但是,纪元通常以另一个可以指定的单位存储。让我们再举一个例子

import pandas as pd

print pd.Timestamp(1587687255,unit='s')

其 **输出** 如下:

2020-04-24 00:14:15

创建时间范围

import pandas as pd

print pd.date_range("11:00", "13:30", freq="30min").time

其 **输出** 如下:

[datetime.time(11, 0) datetime.time(11, 30) datetime.time(12, 0)
datetime.time(12, 30) datetime.time(13, 0) datetime.time(13, 30)]

更改时间频率

import pandas as pd

print pd.date_range("11:00", "13:30", freq="H").time

其 **输出** 如下:

[datetime.time(11, 0) datetime.time(12, 0) datetime.time(13, 0)]

转换为时间戳

要转换日期型对象的Series或类似列表的对象(例如字符串、纪元或混合),可以使用to_datetime函数。传递时,这将返回一个Series(具有相同的索引),而类似列表的对象将转换为DatetimeIndex。看看下面的例子−

import pandas as pd

print pd.to_datetime(pd.Series(['Jul 31, 2009','2010-01-10', None]))

其 **输出** 如下:

0  2009-07-31
1  2010-01-10
2         NaT
dtype: datetime64[ns]

NaT表示非时间(相当于NaN)

让我们再举一个例子。

import pandas as pd

print pd.to_datetime(['2005/11/23', '2010.12.31', None])

其 **输出** 如下:

DatetimeIndex(['2005-11-23', '2010-12-31', 'NaT'], dtype='datetime64[ns]', freq=None)

Python Pandas - 日期功能

扩展时间序列,日期功能在金融数据分析中起着重要作用。处理日期数据时,我们经常会遇到以下情况−

  • 生成日期序列
  • 将日期序列转换为不同的频率

创建日期范围

通过指定周期和频率,使用date.range()函数,我们可以创建日期序列。默认情况下,范围的频率是天。

import pandas as pd

print pd.date_range('1/1/2011', periods=5)

其 **输出** 如下:

DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'],
   dtype='datetime64[ns]', freq='D')

更改日期频率

import pandas as pd

print pd.date_range('1/1/2011', periods=5,freq='M')

其 **输出** 如下:

DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-30', '2011-05-31'],
   dtype='datetime64[ns]', freq='M')

bdate_range

bdate_range()代表业务日期范围。与date_range()不同,它不包括周六和周日。

import pandas as pd

print pd.date_range('1/1/2011', periods=5)

其 **输出** 如下:

DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'],
   dtype='datetime64[ns]', freq='D')

观察,3月3日之后,日期跳到3月6日,排除了4日和5日。只需查看一下您的日历即可确认日期。

诸如 **date_range** 和 **bdate_range** 之类的便捷函数使用了多种频率别名。date_range 的默认频率为日历日,而 bdate_range 的默认频率为工作日。

import pandas as pd
start = pd.datetime(2011, 1, 1)
end = pd.datetime(2011, 1, 5)

print pd.date_range(start, end)

其 **输出** 如下:

DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'],
   dtype='datetime64[ns]', freq='D')

偏移别名

许多字符串别名被赋予有用的常用时间序列频率。我们将这些别名称为偏移别名。

别名 描述 别名 描述
B 工作日频率 BQS 工作季度开始频率
D 日历日频率 A 年度(年)末频率
W 每周频率 BA 工作年度末频率
M 月末频率 BAS 工作年度开始频率
SM 半月末频率 BH 工作小时频率
BM 工作月末频率 H 每小时频率
MS 月开始频率 T, min 分钟频率
SMS 半月开始频率 S 秒频率
BMS 工作月开始频率 L, ms 毫秒
Q 季度末频率 U, us 微秒
BQ 工作季度末频率 N 纳秒
QS 季度开始频率

Python Pandas - Timedelta

Timedeltas 是时间的差值,以不同的单位表示,例如天、小时、分钟、秒。它们可以是正数也可以是负数。

我们可以使用如下所示的各种参数创建 Timedelta 对象:

字符串

通过传递字符串字面量,我们可以创建一个 timedelta 对象。

import pandas as pd

print pd.Timedelta('2 days 2 hours 15 minutes 30 seconds')

其 **输出** 如下:

2 days 02:15:30

整数

通过传递带有单位的整数值,参数创建一个 Timedelta 对象。

import pandas as pd

print pd.Timedelta(6,unit='h')

其 **输出** 如下:

0 days 06:00:00

数据偏移量

数据偏移量,例如周、天、小时、分钟、秒、毫秒、微秒、纳秒,也可以用于构造。

import pandas as pd

print pd.Timedelta(days=2)

其 **输出** 如下:

2 days 00:00:00

to_timedelta()

使用顶级 **pd.to_timedelta**,您可以将标量、数组、列表或序列从识别的 timedelta 格式/值转换为 Timedelta 类型。如果输入是 Series,它将构造 Series;如果输入是标量类型,它将构造标量;否则将输出 **TimedeltaIndex**。

import pandas as pd

print pd.Timedelta(days=2)

其 **输出** 如下:

2 days 00:00:00

操作

您可以对 Series/DataFrame 进行操作,并通过对 **datetime64[ns]** Series 或 Timestamps 进行减法运算来构造 **timedelta64[ns]** Series。

现在让我们创建一个包含 Timedelta 和 datetime 对象的 DataFrame,并对其进行一些算术运算:

import pandas as pd

s = pd.Series(pd.date_range('2012-1-1', periods=3, freq='D'))
td = pd.Series([ pd.Timedelta(days=i) for i in range(3) ])
df = pd.DataFrame(dict(A = s, B = td))

print df

其 **输出** 如下:

            A      B
0  2012-01-01 0 days
1  2012-01-02 1 days
2  2012-01-03 2 days

加法运算

import pandas as pd

s = pd.Series(pd.date_range('2012-1-1', periods=3, freq='D'))
td = pd.Series([ pd.Timedelta(days=i) for i in range(3) ])
df = pd.DataFrame(dict(A = s, B = td))
df['C']=df['A']+df['B']

print df

其 **输出** 如下:

           A      B          C
0 2012-01-01 0 days 2012-01-01
1 2012-01-02 1 days 2012-01-03
2 2012-01-03 2 days 2012-01-05

减法运算

import pandas as pd

s = pd.Series(pd.date_range('2012-1-1', periods=3, freq='D'))
td = pd.Series([ pd.Timedelta(days=i) for i in range(3) ])
df = pd.DataFrame(dict(A = s, B = td))
df['C']=df['A']+df['B']
df['D']=df['C']+df['B']

print df

其 **输出** 如下:

           A      B          C          D
0 2012-01-01 0 days 2012-01-01 2012-01-01
1 2012-01-02 1 days 2012-01-03 2012-01-04
2 2012-01-03 2 days 2012-01-05 2012-01-07

Python Pandas - 分类数据

在实际应用中,数据经常包含重复的文本列。诸如性别、国家和代码之类的特征总是重复的。这些是分类数据的示例。

分类变量只能取有限的、通常是固定的可能值。除了固定长度外,分类数据可能具有顺序,但不能执行数值运算。分类数据是一种 Pandas 数据类型。

分类数据类型在以下情况下非常有用:

  • 仅包含少量不同值的字符串变量。将此类字符串变量转换为分类变量可以节省一些内存。

  • 变量的词法顺序与其逻辑顺序不同(“一”、“二”、“三”)。通过转换为分类变量并在类别上指定顺序,排序和最小/最大值将使用逻辑顺序而不是词法顺序。

  • 作为其他 Python 库的信号,表明此列应被视为分类变量(例如,使用合适的统计方法或绘图类型)。

对象创建

分类对象可以通过多种方式创建。下面描述了不同的方法:

category

在 pandas 对象创建中将 dtype 指定为“category”。

import pandas as pd

s = pd.Series(["a","b","c","a"], dtype="category")
print s

其 **输出** 如下:

0  a
1  b
2  c
3  a
dtype: category
Categories (3, object): [a, b, c]

传递给 series 对象的元素数量为四个,但类别只有三个。在输出类别中观察到相同的情况。

pd.Categorical

使用标准 pandas Categorical 构造函数,我们可以创建一个类别对象。

pandas.Categorical(values, categories, ordered)

让我们来看一个例子:

import pandas as pd

cat = pd.Categorical(['a', 'b', 'c', 'a', 'b', 'c'])
print cat

其 **输出** 如下:

[a, b, c, a, b, c]
Categories (3, object): [a, b, c]

让我们再来看一个例子:

import pandas as pd

cat = cat=pd.Categorical(['a','b','c','a','b','c','d'], ['c', 'b', 'a'])
print cat

其 **输出** 如下:

[a, b, c, a, b, c, NaN]
Categories (3, object): [c, b, a]

这里,第二个参数表示类别。因此,任何不在类别中的值都将被视为 **NaN**。

现在,让我们来看下面的例子:

import pandas as pd

cat = cat=pd.Categorical(['a','b','c','a','b','c','d'], ['c', 'b', 'a'],ordered=True)
print cat

其 **输出** 如下:

[a, b, c, a, b, c, NaN]
Categories (3, object): [c < b < a]

逻辑上,顺序意味着 **a** 大于 **b**,**b** 大于 **c**。

描述

对分类数据使用 **.describe()** 命令,我们得到与 **type** 为字符串的 **Series** 或 **DataFrame** 类似的输出。

import pandas as pd
import numpy as np

cat = pd.Categorical(["a", "c", "c", np.nan], categories=["b", "a", "c"])
df = pd.DataFrame({"cat":cat, "s":["a", "c", "c", np.nan]})

print df.describe()
print df["cat"].describe()

其 **输出** 如下:

       cat s
count    3 3
unique   2 2
top      c c
freq     2 2
count     3
unique    2
top       c
freq      2
Name: cat, dtype: object

获取类别的属性

**obj.cat.categories** 命令用于获取 **对象的类别**。

import pandas as pd
import numpy as np

s = pd.Categorical(["a", "c", "c", np.nan], categories=["b", "a", "c"])
print s.categories

其 **输出** 如下:

Index([u'b', u'a', u'c'], dtype='object')

**obj.ordered** 命令用于获取对象的顺序。

import pandas as pd
import numpy as np

cat = pd.Categorical(["a", "c", "c", np.nan], categories=["b", "a", "c"])
print cat.ordered

其 **输出** 如下:

False

该函数返回 **false**,因为我们没有指定任何顺序。

重命名类别

重命名类别是通过将新值赋给 **series.cat.categories** 属性来完成的。

import pandas as pd

s = pd.Series(["a","b","c","a"], dtype="category")
s.cat.categories = ["Group %s" % g for g in s.cat.categories]
print s.cat.categories

其 **输出** 如下:

Index([u'Group a', u'Group b', u'Group c'], dtype='object')

初始类别 **[a,b,c]** 由对象的 **s.cat.categories** 属性更新。

追加新类别

使用 Categorical.add.categories() 方法,可以追加新的类别。

import pandas as pd

s = pd.Series(["a","b","c","a"], dtype="category")
s = s.cat.add_categories([4])
print s.cat.categories

其 **输出** 如下:

Index([u'a', u'b', u'c', 4], dtype='object')

删除类别

使用 **Categorical.remove_categories()** 方法,可以删除不需要的类别。

import pandas as pd

s = pd.Series(["a","b","c","a"], dtype="category")
print ("Original object:")
print s

print ("After removal:")
print s.cat.remove_categories("a")

其 **输出** 如下:

Original object:
0  a
1  b
2  c
3  a
dtype: category
Categories (3, object): [a, b, c]

After removal:
0  NaN
1  b
2  c
3  NaN
dtype: category
Categories (2, object): [b, c]

分类数据的比较

在三种情况下可以将分类数据与其他对象进行比较:

  • 将相等性(== 和 !=)与与分类数据长度相同的列表状对象(列表、Series、数组……)进行比较。

  • 当 ordered==True 且类别相同时,将分类数据与另一个分类 Series 进行所有比较(==、!=、>、>=、< 和 <=)。

  • 将分类数据与标量进行所有比较。

让我们来看下面的例子:

import pandas as pd

cat = pd.Series([1,2,3]).astype("category", categories=[1,2,3], ordered=True)
cat1 = pd.Series([2,2,2]).astype("category", categories=[1,2,3], ordered=True)

print cat>cat1

其 **输出** 如下:

0  False
1  False
2  True
dtype: bool

Python Pandas - 可视化

基本绘图:plot

Series 和 DataFrame 上的此功能只是 **matplotlib** **库 plot()** 方法的一个简单包装器。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10,4),index=pd.date_range('1/1/2000',
   periods=10), columns=list('ABCD'))

df.plot()

其 **输出** 如下:

Basic Plotting

如果索引包含日期,它将调用 **gct().autofmt_xdate()** 以格式化 x 轴,如上图所示。

我们可以使用 **x** 和 **y** 关键字绘制一列与另一列的关系图。

绘图方法允许使用少数几种除默认线图以外的绘图样式。这些方法可以作为 **plot()** 的 kind 关键字参数提供。这些包括:

  • bar 或 barh 用于条形图
  • hist 用于直方图
  • box 用于箱线图
  • 'area' 用于面积图
  • 'scatter' 用于散点图

条形图

现在让我们通过创建一个条形图来看看什么是条形图。条形图可以通过以下方式创建:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(10,4),columns=['a','b','c','d')
df.plot.bar()

其 **输出** 如下:

Bar Plot

要生成堆叠条形图,请 **传递 stacked=True**:

import pandas as pd
df = pd.DataFrame(np.random.rand(10,4),columns=['a','b','c','d')
df.plot.bar(stacked=True)

其 **输出** 如下:

Stacked Bar Plot

要获取水平条形图,请使用 **barh** 方法:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(10,4),columns=['a','b','c','d')

df.plot.barh(stacked=True)

其 **输出** 如下:

Horizontal Bar Plot

直方图

可以使用 **plot.hist()** 方法绘制直方图。我们可以指定箱数。

import pandas as pd
import numpy as np

df = pd.DataFrame({'a':np.random.randn(1000)+1,'b':np.random.randn(1000),'c':
np.random.randn(1000) - 1}, columns=['a', 'b', 'c'])

df.plot.hist(bins=20)

其 **输出** 如下:

Histograms using plot.hist()

要为每一列绘制不同的直方图,请使用以下代码:

import pandas as pd
import numpy as np

df=pd.DataFrame({'a':np.random.randn(1000)+1,'b':np.random.randn(1000),'c':
np.random.randn(1000) - 1}, columns=['a', 'b', 'c'])

df.diff.hist(bins=20)

其 **输出** 如下:

Histograms for Column

箱线图

可以通过调用 **Series.box.plot()** 和 **DataFrame.box.plot()**,或者 **DataFrame.boxplot()** 来绘制箱线图,以可视化每一列中值的分布。

例如,这是一个箱线图,它表示在 [0,1) 上进行 10 次观察的 5 次均匀随机变量试验。

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(10, 5), columns=['A', 'B', 'C', 'D', 'E'])
df.plot.box()

其 **输出** 如下:

Box Plots

面积图

可以使用 **Series.plot.area()** 或 **DataFrame.plot.area()** 方法创建面积图。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
df.plot.area()

其 **输出** 如下:

Area Plot

散点图

可以使用 **DataFrame.plot.scatter()** 方法创建散点图。

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(50, 4), columns=['a', 'b', 'c', 'd'])
df.plot.scatter(x='a', y='b')

其 **输出** 如下:

Scatter Plot

饼图

可以使用 **DataFrame.plot.pie()** 方法创建饼图。

import pandas as pd
import numpy as np

df = pd.DataFrame(3 * np.random.rand(4), index=['a', 'b', 'c', 'd'], columns=['x'])
df.plot.pie(subplots=True)

其 **输出** 如下:

Pie Chart

Python Pandas - I/O 工具

**Pandas I/O API** 是一组顶级读取器函数,类似于 **pd.read_csv()**,通常返回 Pandas 对象。

用于读取文本文件(或平面文件)的两个主要函数是 **read_csv()** 和 **read_table()**。它们都使用相同的解析代码将表格数据智能地转换为 **DataFrame** 对象:

pandas.read_csv(filepath_or_buffer, sep=',', delimiter=None, header='infer',
names=None, index_col=None, usecols=None

pandas.read_csv(filepath_or_buffer, sep='\t', delimiter=None, header='infer',
names=None, index_col=None, usecols=None

以下是 **csv** 文件数据的样子:

S.No,Name,Age,City,Salary
1,Tom,28,Toronto,20000
2,Lee,32,HongKong,3000
3,Steven,43,Bay Area,8300
4,Ram,38,Hyderabad,3900

将此数据另存为 **temp.csv** 并对其进行操作。

S.No,Name,Age,City,Salary
1,Tom,28,Toronto,20000
2,Lee,32,HongKong,3000
3,Steven,43,Bay Area,8300
4,Ram,38,Hyderabad,3900

将此数据另存为 **temp.csv** 并对其进行操作。

read.csv

**read.csv** 从 csv 文件读取数据并创建 DataFrame 对象。

import pandas as pd

df=pd.read_csv("temp.csv")
print df

其 **输出** 如下:

   S.No     Name   Age       City   Salary
0     1      Tom    28    Toronto    20000
1     2      Lee    32   HongKong     3000
2     3   Steven    43   Bay Area     8300
3     4      Ram    38  Hyderabad     3900

自定义索引

这指定了 csv 文件中的一列,可以使用 **index_col** 来自定义索引。

import pandas as pd

df=pd.read_csv("temp.csv",index_col=['S.No'])
print df

其 **输出** 如下:

S.No   Name   Age       City   Salary
1       Tom    28    Toronto    20000
2       Lee    32   HongKong     3000
3    Steven    43   Bay Area     8300
4       Ram    38  Hyderabad     3900

转换器

列的 **dtype** 可以作为字典传递。

import pandas as pd

df = pd.read_csv("temp.csv", dtype={'Salary': np.float64})
print df.dtypes

其 **输出** 如下:

S.No       int64
Name      object
Age        int64
City      object
Salary   float64
dtype: object

默认情况下,Salary 列的 **dtype** 是 **int**,但结果显示为 **float**,因为我们已显式转换了类型。

因此,数据看起来像浮点数:

  S.No   Name   Age      City    Salary
0   1     Tom   28    Toronto   20000.0
1   2     Lee   32   HongKong    3000.0
2   3  Steven   43   Bay Area    8300.0
3   4     Ram   38  Hyderabad    3900.0

header_names

使用 names 参数指定 header 的名称。

import pandas as pd
 
df=pd.read_csv("temp.csv", names=['a', 'b', 'c','d','e'])
print df

其 **输出** 如下:

       a        b    c           d        e
0   S.No     Name   Age       City   Salary
1      1      Tom   28     Toronto    20000
2      2      Lee   32    HongKong     3000
3      3   Steven   43    Bay Area     8300
4      4      Ram   38   Hyderabad     3900

观察到,header 名称已附加了自定义名称,但文件中的 header 尚未删除。现在,我们使用 header 参数将其删除。

如果 header 不在第一行,则将行号传递给 header。这将跳过前面的行。

import pandas as pd 

df=pd.read_csv("temp.csv",names=['a','b','c','d','e'],header=0)
print df

其 **输出** 如下:

      a        b    c           d        e
0  S.No     Name   Age       City   Salary
1     1      Tom   28     Toronto    20000
2     2      Lee   32    HongKong     3000
3     3   Steven   43    Bay Area     8300
4     4      Ram   38   Hyderabad     3900

skiprows

skiprows 跳过指定数量的行。

import pandas as pd

df=pd.read_csv("temp.csv", skiprows=2)
print df

其 **输出** 如下:

    2      Lee   32    HongKong   3000
0   3   Steven   43    Bay Area   8300
1   4      Ram   38   Hyderabad   3900

Python Pandas - 稀疏数据

当任何与特定值匹配的数据(NaN/缺失值,尽管可以选择任何值)被省略时,稀疏对象会被“压缩”。一个特殊的 SparseIndex 对象跟踪数据被“稀疏化”的位置。在一个例子中,这将更有意义。所有标准的 Pandas 数据结构都应用 **to_sparse** 方法:

import pandas as pd
import numpy as np

ts = pd.Series(np.random.randn(10))
ts[2:-2] = np.nan
sts = ts.to_sparse()
print sts

其 **输出** 如下:

0   -0.810497
1   -1.419954
2         NaN
3         NaN
4         NaN
5         NaN
6         NaN
7         NaN
8    0.439240
9   -1.095910
dtype: float64
BlockIndex
Block locations: array([0, 8], dtype=int32)
Block lengths: array([2, 2], dtype=int32)

稀疏对象的存在是为了提高内存效率。

现在让我们假设您有一个大型 NA DataFrame 并执行以下代码:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10000, 4))
df.ix[:9998] = np.nan
sdf = df.to_sparse()

print sdf.density

其 **输出** 如下:

0.0001

任何稀疏对象都可以通过调用 **to_dense** 转换回标准密集形式:

import pandas as pd
import numpy as np
ts = pd.Series(np.random.randn(10))
ts[2:-2] = np.nan
sts = ts.to_sparse()
print sts.to_dense()

其 **输出** 如下:

0   -0.810497
1   -1.419954
2         NaN
3         NaN
4         NaN
5         NaN
6         NaN
7         NaN
8    0.439240
9   -1.095910
dtype: float64

稀疏 Dtypes

稀疏数据应与其密集表示具有相同的 dtype。目前,支持 **float64、int64** 和 **booldtypes**。根据原始 **dtype,fill_value 默认值** 会发生变化:

  • **float64** − np.nan

  • **int64** − 0

  • **bool** − False

让我们执行以下代码来了解这一点:

import pandas as pd
import numpy as np

s = pd.Series([1, np.nan, np.nan])
print s

s.to_sparse()
print s

其 **输出** 如下:

0   1.0
1   NaN
2   NaN
dtype: float64

0   1.0
1   NaN
2   NaN
dtype: float64

Python Pandas - 警告和陷阱

Caveats 表示警告,gotcha 表示未发现的问题。

在 Pandas 中使用 If/Truth 语句

Pandas 遵循 numpy 的约定,在尝试将某些内容转换为布尔值 (bool) 时会引发错误。这发生在使用布尔运算符 `if` 或 `when`,以及 `and`、`or` 或 `not` 的情况下。结果应该是什么并不明确。因为它不是零长度,所以应该是 True 吗?因为存在 False 值,所以应该是 False 吗?这不明确,因此 Pandas 会引发ValueError

import pandas as pd

if pd.Series([False, True, False]):
   print 'I am True'

其 **输出** 如下:

ValueError: The truth value of a Series is ambiguous. 
Use a.empty, a.bool() a.item(),a.any() or a.all().

在 `if` 条件中,不清楚该如何处理。该错误提示是否应该使用 `None` 或其中任何一个

import pandas as pd

if pd.Series([False, True, False]).any():
   print("I am any")

其 **输出** 如下:

I am any

要在布尔上下文中评估单元素 Pandas 对象,请使用 `.bool()` 方法。

import pandas as pd

print pd.Series([True]).bool()

其 **输出** 如下:

True

按位布尔运算

像 `==` 和 `!=` 这样的按位布尔运算符将返回一个布尔序列,而这几乎总是需要的。

import pandas as pd

s = pd.Series(range(5))
print s==4

其 **输出** 如下:

0 False
1 False
2 False
3 False
4 True
dtype: bool

isin 操作

这将返回一个布尔序列,显示 Series 中的每个元素是否完全包含在传递的值序列中。

import pandas as pd

s = pd.Series(list('abc'))
s = s.isin(['a', 'c', 'e'])
print s

其 **输出** 如下:

0 True
1 False
2 True
dtype: bool

重新索引与 ix 的陷阱

许多用户会发现自己使用ix 索引功能作为从 Pandas 对象中选择数据的简洁方法。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(6, 4), columns=['one', 'two', 'three',
'four'],index=list('abcdef'))

print df
print df.ix[['b', 'c', 'e']]

其 **输出** 如下:

          one        two      three       four
a   -1.582025   1.335773   0.961417  -1.272084
b    1.461512   0.111372  -0.072225   0.553058
c   -1.240671   0.762185   1.511936  -0.630920
d   -2.380648  -0.029981   0.196489   0.531714
e    1.846746   0.148149   0.275398  -0.244559
f   -1.842662  -0.933195   2.303949   0.677641

          one        two      three       four
b    1.461512   0.111372  -0.072225   0.553058
c   -1.240671   0.762185   1.511936  -0.630920
e    1.846746   0.148149   0.275398  -0.244559

当然,在这种情况下,这与使用reindex方法完全等效。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(6, 4), columns=['one', 'two', 'three',
'four'],index=list('abcdef'))

print df
print df.reindex(['b', 'c', 'e'])

其 **输出** 如下:

          one        two      three       four
a    1.639081   1.369838   0.261287  -1.662003
b   -0.173359   0.242447  -0.494384   0.346882
c   -0.106411   0.623568   0.282401  -0.916361
d   -1.078791  -0.612607  -0.897289  -1.146893
e    0.465215   1.552873  -1.841959   0.329404
f    0.966022  -0.190077   1.324247   0.678064

          one        two      three       four
b   -0.173359   0.242447  -0.494384   0.346882
c   -0.106411   0.623568   0.282401  -0.916361
e    0.465215   1.552873  -1.841959   0.329404

根据这一点,有些人可能会得出结论,ixreindex是 100% 等效的。除了整数索引的情况外,这是正确的。例如,上述操作可以另一种方式表达为:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(6, 4), columns=['one', 'two', 'three',
'four'],index=list('abcdef'))

print df
print df.ix[[1, 2, 4]]
print df.reindex([1, 2, 4])

其 **输出** 如下:

          one        two      three       four
a   -1.015695  -0.553847   1.106235  -0.784460
b   -0.527398  -0.518198  -0.710546  -0.512036
c   -0.842803  -1.050374   0.787146   0.205147
d   -1.238016  -0.749554  -0.547470  -0.029045
e   -0.056788   1.063999  -0.767220   0.212476
f    1.139714   0.036159   0.201912   0.710119

          one        two      three       four
b   -0.527398  -0.518198  -0.710546  -0.512036
c   -0.842803  -1.050374   0.787146   0.205147
e   -0.056788   1.063999  -0.767220   0.212476

    one  two  three  four
1   NaN  NaN    NaN   NaN
2   NaN  NaN    NaN   NaN
4   NaN  NaN    NaN   NaN

重要的是要记住,reindex 仅是严格的标签索引。在索引包含整数和字符串等病态情况下,这可能会导致一些潜在的意外结果。

Python Pandas - 与 SQL 的比较

由于许多潜在的 Pandas 用户都熟悉 SQL,因此本页旨在提供一些关于如何使用 pandas 执行各种 SQL 操作的示例。

import pandas as pd

url = 'https://raw.github.com/pandasdev/
pandas/master/pandas/tests/data/tips.csv'

tips=pd.read_csv(url)
print tips.head()

其 **输出** 如下:

    total_bill   tip      sex  smoker  day     time  size
0        16.99  1.01   Female      No  Sun  Dinner      2
1        10.34  1.66     Male      No  Sun  Dinner      3
2        21.01  3.50     Male      No  Sun  Dinner      3
3        23.68  3.31     Male      No  Sun  Dinner      2
4        24.59  3.61   Female      No  Sun  Dinner      4

SELECT

在 SQL 中,选择是使用逗号分隔的列列表(或 `*` 选择所有列)来完成的。

SELECT total_bill, tip, smoker, time
FROM tips
LIMIT 5;

在 Pandas 中,列选择是通过将列名列表传递给您的 DataFrame 来完成的。

tips[['total_bill', 'tip', 'smoker', 'time']].head(5)

让我们检查完整的程序。

import pandas as pd

url = 'https://raw.github.com/pandasdev/
pandas/master/pandas/tests/data/tips.csv'
 
tips=pd.read_csv(url)
print tips[['total_bill', 'tip', 'smoker', 'time']].head(5)

其 **输出** 如下:

   total_bill   tip  smoker     time
0       16.99  1.01      No   Dinner
1       10.34  1.66      No   Dinner
2       21.01  3.50      No   Dinner
3       23.68  3.31      No   Dinner
4       24.59  3.61      No   Dinner

在不带列名列表的情况下调用 DataFrame 将显示所有列(类似于 SQL 的 `*`)。

WHERE

在 SQL 中,过滤是通过 WHERE 子句完成的。

  SELECT * FROM tips WHERE time = 'Dinner' LIMIT 5;

DataFrame 可以通过多种方式进行过滤;其中最直观的是使用布尔索引。

  tips[tips['time'] == 'Dinner'].head(5)

让我们检查完整的程序。

import pandas as pd

url = 'https://raw.github.com/pandasdev/
pandas/master/pandas/tests/data/tips.csv'

tips=pd.read_csv(url)
print tips[tips['time'] == 'Dinner'].head(5)

其 **输出** 如下:

   total_bill   tip      sex  smoker  day    time  size
0       16.99  1.01   Female     No   Sun  Dinner    2
1       10.34  1.66     Male     No   Sun  Dinner    3
2       21.01  3.50     Male     No   Sun  Dinner    3
3       23.68  3.31     Male     No   Sun  Dinner    2
4       24.59  3.61   Female     No   Sun  Dinner    4

上面的语句将一个 True/False 对象的序列传递给 DataFrame,返回所有值为 True 的行。

GroupBy

此操作获取整个数据集中每个组中记录的数量。例如,查询获取按性别留下的消费小费数量:

SELECT sex, count(*)
FROM tips
GROUP BY sex;

Pandas 等效项将是:

tips.groupby('sex').size()

让我们检查完整的程序。

import pandas as pd

url = 'https://raw.github.com/pandasdev/
pandas/master/pandas/tests/data/tips.csv'

tips=pd.read_csv(url)
print tips.groupby('sex').size()

其 **输出** 如下:

sex
Female   87
Male    157
dtype: int64

前 N 行

SQL 使用LIMIT返回前 n 行

SELECT * FROM tips
LIMIT 5 ;

Pandas 等效项将是:

tips.head(5)

让我们检查完整的示例。

import pandas as pd

url = 'https://raw.github.com/pandas-dev/pandas/master/pandas/tests/data/tips.csv'

tips=pd.read_csv(url)
tips = tips[['smoker', 'day', 'time']].head(5)
print tips

其 **输出** 如下:

   smoker   day     time
0      No   Sun   Dinner
1      No   Sun   Dinner
2      No   Sun   Dinner
3      No   Sun   Dinner
4      No   Sun   Dinner

这些是我们之前章节中学习的 Pandas 库中比较的几个基本操作。

广告