数据科学 IPython 笔记本 7.6 Pandas 中的数据操作

7.6 Pandas 中的数据操作

原文:Operating on Data in Pandas

译者:飞龙

协议:CC BY-NC-SA 4.0

本节是《Python 数据科学手册》(Python Data Science Handbook)的摘录。

NumPy 的一个重要部分是能够执行快速的逐元素运算,包括基本算术(加法,减法,乘法等),和更复杂的运算(三角函数,指数函数和对数函数等)。Pandas 从 NumPy 继承了大部分功能,我们在“NumPy 数组上的计算:通用函数”中介绍的ufunc对此至关重要。

Pandas 包含一些有用的调整,但是:对于一元操作,如取负和三角函数,这些ufunc将保留输出中的索引和列标签,对于二元操作,如加法和乘法,将对象传递给ufunc时,Pandas 将自动对齐索引。这意味着,保留数据的上下文并组合来自不同来源的数据 - 这两个在原始的 NumPy 数组中可能容易出错的任务 - 对于 Pandas 来说基本上是万无一失的。我们还将看到,在一维Series结构和二维DataFrame结构之间有明确定义的操作。

通用函数:索引保留

因为 Pandas 为兼容 NumPy 而设计,所以任何 NumPy ufunc都可以用于 Pandas SeriesDataFrame对象。让我们首先定义一个简单的SeriesDataFrame来演示它:

import pandas as pd
import numpy as np

rng = np.random.RandomState(42)
ser = pd.Series(rng.randint(0, 10, 4))
ser

'''
0    6
1    3
2    7
3    4
dtype: int64
'''

df = pd.DataFrame(rng.randint(0, 10, (3, 4)),
                  columns=['A', 'B', 'C', 'D'])
df
A B C D
0 6 9 2 6
1 7 4 3 7
2 7 2 5 4

如果我们在这些对象中的任何一个上应用 NumPy ufunc,结果将是保留索引的另一个 Pandas 对象:

np.exp(ser)

'''
0     403.428793
1      20.085537
2    1096.633158
3      54.598150
dtype: float64
'''

或者,对于稍微复杂的计算:

np.sin(df * np.pi / 4)
A B C D
0 -1.000000 7.071068e-01 1.000000 -1.000000e+00
1 -0.707107 1.224647e-16 0.707107 -7.071068e-01
2 -0.707107 1.000000e+00 -0.707107 1.224647e-16

“NumPy 数组上的计算:通用函数”中讨论的任何ufunc都可以以类似的方式使用。

通用函数:索引对齐

对于两个SeriesDataFrame对象的二元操作,Pandas 将在执行操作的过程中对齐索引。这在处理不完整数据时非常方便,我们将在后面的一些示例中看到。

序列中的索引对齐

例如,假设我们正在组合两个不同的数据源,并且按照面积,找到美国前三的州,并且按人口找到美国前三的州:

area = pd.Series({'Alaska': 1723337, 'Texas': 695662,
                  'California': 423967}, name='area')
population = pd.Series({'California': 38332521, 'Texas': 26448193,
                        'New York': 19651127}, name='population')

让我们看看,当我们将这些分开以计算人口密度时会发生什么:

population / area

'''
Alaska              NaN
California    90.413926
New York            NaN
Texas         38.018740
dtype: float64
'''

所得数组包含两个输入数组的索引的并集,可以使用这些索引上的标准 Python 集合算法来确定:

area.index | population.index

# Index(['Alaska', 'California', 'New York', 'Texas'], dtype='object')

任何没有条目的项目都标为NaN(非数字),这就是 Pandas 标记缺失数据的方式(请在“处理缺失数据”中参阅缺失数据的进一步讨论)。对于 Python 的任何内置算术表达式,索引匹配是以这种方式实现的;默认情况下,任何缺失值都使用NaN填充:

A = pd.Series([2, 4, 6], index=[0, 1, 2])
B = pd.Series([1, 3, 5], index=[1, 2, 3])
A + B

'''
0    NaN
1    5.0
2    9.0
3    NaN
dtype: float64
'''

如果使用NaN值不是所需的行为,则可以使用适当的对象方法代替运算符来修改填充值。例如,调用A.add(B)相当于调用A + B,但对于A或``B`中的任何可能会缺失的元素,可以显式指定的填充值:

A.add(B, fill_value=0)

'''
0    2.0
1    5.0
2    9.0
3    5.0
dtype: float64
'''

数据帧中的索引对齐

DataFrames上执行操作时,列和索引都会发生类似的对齐:

A = pd.DataFrame(rng.randint(0, 20, (2, 2)),
                 columns=list('AB'))
A
A B
0 1 11
1 5 1
B = pd.DataFrame(rng.randint(0, 10, (3, 3)),
                 columns=list('BAC'))
B
B A C
0 4 0 9
1 5 8 0
2 9 2 6
A + B
A B C
0 1.0 15.0 NaN
1 13.0 6.0 NaN
2 NaN NaN NaN

请注意,索引是正确对齐的,无论它们在两个对象中的顺序如何,并且结果中的索引都是有序的。与Series的情况一样,我们可以使用相关对象的算术方法,并传递任何所需的fill_value来替代缺失的条目。这里我们将填充A中所有值的均值(通过首先堆叠A的行来计算):

fill = A.stack().mean()
A.add(B, fill_value=fill)
A B C
0 1.0 15.0 13.5
1 13.0 6.0 4.5
2 6.5 13.5 10.5

下表列出了 Python 运算符及其等效的 Pandas 对象方法:

Python 运算符 Pandas 方法
+ add()
- sub(), subtract()
* mul(), multiply()
/ truediv(), div(), divide()
// floordiv()
% mod()
** pow()

通用函数:数据帧和序列之间的操作

执行DataFrameSeries之间的操作时,与之相似,索引和列是保持对齐的。DataFrameSeries之间的操作,类似于二维和一维 NumPy 数组之间的操作。考虑一个常见的操作,我们计算二维数组与其中一行的差:

A = rng.randint(10, size=(3, 4))
A

'''
array([[3, 8, 2, 4],
       [2, 6, 4, 8],
       [6, 1, 3, 8]])
'''

A - A[0]

'''
array([[ 0,  0,  0,  0],
       [-1, -2,  2,  4],
       [ 3, -7,  1,  4]])
'''

根据 NumPy 的广播规则(参见“数据计算:广播”),二维数组与其中一行之间的减法是逐行应用的。

在 Pandas 中,按照惯例,默认情况下逐行操作:

df = pd.DataFrame(A, columns=list('QRST'))
df - df.iloc[0]
Q R S T
0 0 0 0 0
1 -1 -2 2 4
2 3 -7 1 4

如果你希望逐列操作,则可以使用前面提到的对象方法,同时指定axis关键字:

df.subtract(df['R'], axis=0)
Q R S T
0 -5 0 -6 -4
1 -4 0 -2 2
2 5 0 2 7

请注意,这些DataFrameSeries操作,如上面讨论的操作,将自动对齐两个元素之间的索引:

halfrow = df.iloc[0, ::2]
halfrow

'''
Q    3
S    2
Name: 0, dtype: int64
'''

df - halfrow
Q R S T
0 0.0 NaN 0.0 NaN
1 -1.0 NaN 2.0 NaN
2 3.0 NaN 1.0 NaN

索引和列的保留和对齐意味着,Pandas 中的数据操作将始终维护数据上下文,这可以防止在处理原始 NumPy 数组中的异构和/或未对齐数据时,可能出现的愚蠢错误。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • (1) 下着毛毛细雨,我伏在栏杆上看赛龙舟的出发,鞭炮声吆喝声此起彼伏,拍不到近景...
    恰妈阅读 248评论 4 12
  • 背影 致谭玉华同学 作者:荒古百川流 你的背影 很美, 映印在年少的心里。 似滴水, 落在平静的湖面, 瞬间 击起...
    彭北阅读 289评论 0 0
  • 反反复复的出去旅游了多次,但是以前很少有做过攻略的,因为“说走就走”的旅行总是能让你感觉满是激情。但是实际上每次在...
    夜猫子谭娟阅读 303评论 0 0