-
2012 年 Wes McKinney 一本经典的 Python for Data Analysis 由 O'Reilly 出版的。Pandas 参考书 现在有一点过时了 ,他最近宣布新版的新书即将出版 我还是觉得这是一本 瞭解 Pandas 如何作用的必备书 我也欣赏一本更简要的书
-
Learning the Pandas Library 由 Matt Harrison 著作 这不是一本有关资料分析及统计的综合书籍 但如果您只是要学习基本的 Pandas 想要很快的上手
-
Marco Rodriguez 跟 Tim Golden 维护了一个 很棒的部落格称为 Planet Python 您可以到 planetpython.org 这个网站, 订阅 RSS 或者从 推特(Twitter) 的 @PlanetPython 得到最新的文章 里面有很多 Python 资料科学的贡献者 我也强烈建议您订阅 RSS
-
Kyle Polich 运作一个称为 Data Skeptic 的 podcast 它并不是专门讲 Python 但它的制作精良 有很棒的跟这个领域专家座谈 以及 简短的教育课程 大部分的字眼是 有关于机器学习方法 但如果您计画 进一步探索这个学程 这个课程也在其中, 我真的很建议您订阅这个 podcast
The Series Data Structure
-
传递一个 list 的值来新创一个 Series, 当这麽做时, Pandas 会自动从零开始分配索引 并将该series的名称设置为“None”。
-
传入一些资料 索引和名称 资料可以是任何东西,类似阵列(array),像list一样。
-
pandas自动的识别了类型 在list中包含的数据,在这裡我们传入string列表, pandas将这类型设定为object。
In [1]:
import pandas as pd
import numpy as np
In [2]:
animals = ['Tiger', 'Bear', 'Moose','Bear']
pd.Series(animals)
Out[2]:
0 Tiger
1 Bear
2 Moose
3 Bear
dtype: object
In [3]:
numbers = [1, 2, 3]
pd.Series(numbers)
Out[3]:
0 1
1 2
2 3
dtype: int64
-
不一定要使用strings。 如果传入整数列表, 可以看见Pandas设定类型为int64。 在Pandas内部储存series的值,使用NumPy程式库的类型阵列(typed array)。 在处理数据时这提供显著的加速相比于传统 Python的list
-
NumPy 和 Pandas 如何处理遗失的资料: 在Python中,有none type以表示资料缺失。
In [4]:
animals = ['Tiger', 'Bear', None]
pd.Series(animals)
Out[4]:
0 Tiger
1 Bear
2 None
dtype: object
In [5]:
numbers = [1, 2, None]
pd.Series(numbers)
Out[5]:
0 1.0
1 2.0
2 NaN
dtype: float64
- 事实上不能对Nan本身的做相等测试。 因为答案总是错误的。
- 需要使用特殊功能来测试 '不是一个数字'的存在,例如numpy程式库中的isnan。
In [6]:
np.nan == None
Out[6]:
False
In [7]:
np.nan == np.nan
Out[7]:
False
In [8]:
np.isnan(np.nan)
Out[8]:
True
In [9]:
sports = {'Archery': 'Bhutan',
'Golf': 'Scotland',
'Sumo': 'Japan',
'Taekwondo': 'South Korea'}
s = pd.Series(sports)
s
Out[9]:
Archery Bhutan
Golf Scotland
Sumo Japan
Taekwondo South Korea
dtype: object
In [10]:
s.index
Out[10]:
Index(['Archery', 'Golf', 'Sumo', 'Taekwondo'], dtype='object')
In [11]:
s = pd.Series(['Tiger', 'Bear', 'Moose'], index=['India', 'America', 'Canada'])
s
Out[11]:
India Tiger
America Bear
Canada Moose
dtype: object
In [12]:
sports = {'Archery': 'Bhutan',
'Golf': 'Scotland',
'Sumo': 'Japan',
'Taekwondo': 'South Korea'}
s = pd.Series(sports, index=['Golf', 'Sumo', 'Hockey'])
s
Out[12]:
Golf Scotland
Sumo Japan
Hockey NaN
dtype: objec
- series创建完成后, 可以使用index属性获取index对象。
- 也可以将index的创建与数据分离,通过 将index作为列表,明确地传递给series。
那麽如果index中的值列表 与dictionary中用于创建该系列的keys不对齐
- pandas会覆盖自动创建index值,仅只用 你提供的所有的index值。
- 会忽略你的dictionary中所有的keys,当keys不在你的index中,pandas将添加non类型或NaN
Querying a Series
-
Pandas的Series(列表)可以查询,使用索引(index)的位置或索引的标签(label)。
-
要利用数位位置查询,从零开始,使用
iloc
属性。 -
要通过索引标签(label)进行查询,可以使用
loc
属性。 -
以下是维基百科的全国体育赛事数据。假设我们想要列出所有的运动当我们的索引(index),和 国家列表作为值(value)。
sports = {'Archery': 'Bhutan',
'Golf': 'Scotland',
'Sumo': 'Japan',
'Taekwondo': 'South Korea'}
s = pd.Series(sports)
s
>>>
Archery Bhutan
Golf Scotland
Sumo Japan
Taekwondo South Korea
dtype: object
s.iloc[3]
>>> 'South Korea'
s.loc['Golf']
>>> 'Scotland'
s[3]
>>> 'South Korea'
s['Golf']
>>> 'Scotland'
- 请记住,iloc和loc不是方法(method),是属性(attribute)。所以不用括号()来查询它们,而是使用方括号[], 我们称之为索引运算符。在Python中, 这是获取(get)和设置(set)一个项目的方法,根据其使用的背景来决定。
-
这看起来可能有点困惑的,如果你习惯于语言在哪里封装在里面的 属性、变数和性能是常见的,比如在JAVA中。 Pandas试图使我们的程式更具有可读性,并提供一种 智慧语法,使用index操作符直接在series本身。
-
最后两行指令:例如,如果你传入一个整数参数, 运算子会表现得好像你想要通过iloc属性来查询。如果你传入一个物件(object), 它将认为你想要查询使用根据标签(label)的loc属性。
- 那么如果你的index是整数列表会发生什么呢?这有点复杂,pandas无法自动确定 你是打算通过索引位置或索引标签进行查询。所以在series本身使用index操作时,你需要小心。而更安全的选择是更加明确,直接使用 iloc或loc属性。
sports = {99: 'Bhutan',
100: 'Scotland',
101: 'Japan',
102: 'South Korea'}
s = pd.Series(sports)
s[0]
#This won't call s.iloc[0] as one might expect, it generates an error instead
-
一个典型的程式设计方法,要遍历 该series中的所有项目,并调用一个你感兴趣的运算: 例如,我们可以创建一个浮点值的数据组(dataframe)。让我们把这些看作是不同产品的价格。我们可以写一个小的例行程序码,遍历的所有 series中的项目,并将它们加一起以获得总数。
-
Pandas和基础的NumPy程式库支持一个称为 向量化
vectorization.
-
Vectorization与NumPy库中的大部分功能一起使用, 包括sum函数。
-
调用np.sum 并传入一个可遍历迭代的项目。在这里,我们的pandas series。
s = pd.Series([100.00, 120.00, 101.00, 3.00])
s
>>>
0 100.0
1 120.0
2 101.0
3 3.0
dtype: float64
total = 0
for item in s:
total+=item
print(total)
>>> 324.0
total = np.sum(s)
print(total)
>>> 324.0
现在这两种方法产生相同的值,但是哪一种是确实更快吗?
首先,设置一个大系列的随机(random)数字。
-
神奇功能以百分比符号%开头。如果我们打入这个标志%,然后按Tab键, 我们可以看到可用的魔术函数的列表。你也可以编写自己的魔术函数 但这不过是本课程的范围之外。我们实际上会
-
使用所谓的细胞(cellular)魔术函数 -- 以两个百分比的符号开始, 并修改或包装当前Jupyter单元中的程式。
** 要使用的函数称为timeit。你可能已经从名称猜到了,此函数会运行我们的程式几次来确定,平均运行时间。
#this creates a big series of random numbers
s = pd.Series(np.random.randint(0,1000,10000))
s.head()
%%timeit -n 100
summary = 0
for item in s:
summary+=item
>>> 100 loops, best of 3: 1.87 ms per loop
%%timeit -n 100
summary = np.sum(s)
>>>100 loops, best of 3: 107 µs per loop
- 在pandas和NumPy的相关的功能称为广播(broadcasting)。通过broadcasting,你可以对series中的每个值应用操作, 更改series。
- 例如,如果我们想要对每个随机变数增加2, 我们可以使用+=运算符号直接在列表对像上快速地执行。在这里,我只需要使用head运算印出前五项 首先,我想要先来介绍这门课的四位讲师
- 做这的样程序方式是,遍历所有的 列表中的项目和直接增加它的数值。很快的提一下, Pandas确实支持遍历迭代列表项目,很类似于dictionary, 让你容易地把数值分拆开。但如果你发现自己反覆遍历一列表, 你应该质疑你做的方式是否是尽可能最好的。
%%timeit -n 10
s = pd.Series(np.random.randint(0,1000,10000))
for label, value in s.iteritems():
s.loc[label]= value+2
>>>
10 loops, best of 3: 1.65 s per loop
%%timeit -n 10
s = pd.Series(np.random.randint(0,1000,10000))
s+=2
>>>
10 loops, best of 3: 514 µs per loop
- 最后一点要注意的,在使用索引运算来存取列表资料。 .loc属性(attribute) 不仅可以修改数据, 还可以添加新数据。如果作为索引传入的值不存在,则它会添加一个新条目。请记住,指数可以有混合类型。虽然重要的是,要注意在下面的类型是什么, Pandas会根据需要,自动更改基本的NumPy类型。
s = pd.Series([1, 2, 3])
s.loc['Animal'] = 'Bears'
s
>>>
0 1
1 2
2 3
Animal Bears
dtype: object
original_sports = pd.Series({'Archery': 'Bhutan',
'Golf': 'Scotland',
'Sumo': 'Japan',
'Taekwondo': 'South Korea'})
cricket_loving_countries = pd.Series(['Australia',
'Barbados',
'Pakistan',
'England'],
index=['Cricket',
'Cricket',
'Cricket',
'Cricket'])
all_countries = original_sports.append(cricket_loving_countries)
original_sports
Archery Bhutan
Golf Scotland
Sumo Japan
Taekwondo South Korea
dtype: object
cricket_loving_countries
Cricket Australia
Cricket Barbados
Cricket Pakistan
Cricket England
dtype: object
all_countries
Archery Bhutan
Golf Scotland
Sumo Japan
Taekwondo South Korea
Cricket Australia
Cricket Barbados
Cricket Pakistan
Cricket England
dtype: object
all_countries.loc['Cricket']
Cricket Australia
Cricket Barbados
Cricket Pakistan
Cricket England
dtype: object
- 我们回到我们原来的运动列表。可以创建一个带有多个条目的新列表,用 板球索引,然后使用append将它们放在一起。使用append时,有几个重要的注意事项。首先,Pandas将采取你的列表, 并尝试推断使用最好的数据类型。在这个例子中,一切都是字符(string),所以这里没有问题。
- 其次,append方法实际上并没有改变底层的列表。而是返回一个由两个附加在一起组成的新列表。我们可以回溯并列印原始列表值, 看到它们没有改变。
-
这是实际上的一个重大问题 新的Pandas使用者,之前习惯了物件(objects)在原处更改。所以要当心了,不只是append,还有其他的Pandas函数功能。
-
最后,我们看到,当我们查询附加在一起的列表,用板球 作为国家运动的,我们不是得到一个单一的值,而是一个列表。这实际上是很常见的。
The DataFrame Data Structure
-
DataFrame数据结构是Pandas的核心。
-
DataFrame在概念上是一个二维列表(series)对象, 其中有一个索引(index)和多列内容,每列(column)都有一个标签(label)。事实上,列(column)和行(row)之间的区别 实际上只是一个概念上的区别。可以将DataFrame本身视为简单的双轴有标签的阵列。
- 可以以许多不同的方式创建一个DataFrame。例如,你可以使用一组列表(series), 其中每个列表代表一行数据。或者你可以使用一组字典(dictionary), 其中每个字典都代表一行数据。
purchase_1 = pd.Series({'Name': 'Chris',
'Item Purchased': 'Dog Food',
'Cost': 22.50})
purchase_2 = pd.Series({'Name': 'Kevyn',
'Item Purchased': 'Kitty Litter',
'Cost': 2.50})
purchase_3 = pd.Series({'Name': 'Vinod',
'Item Purchased': 'Bird Seed',
'Cost': 5.00})
df = pd.DataFrame([purchase_1, purchase_2, purchase_3], index=['Store 1', 'Store 1', 'Store 2'])
df.head()
>>>
Cost Item Purchased Name
Store 1 22.5 Dog Food Chris
Store 1 2.5 Kitty Litter Kevyn
Store 2 5.0 Bird Seed Vinod
- 与列表(series)类似,可以使用iloc和loc属性提取数据。因为DataFrame是二维的,所以将单一值传递给loc 索引操作将返回一个列表,如果只有一行返回。
df.loc['Store 2']
>>>
Cost 5
Item Purchased Bird Seed
Name Vinod
Name: Store 2, dtype: object
- 列表的名称作为行索引值返回, 而列名(column_name)也包括在输出中。
网友评论