Pandas 操作数据集(最全总结之一)
第1部分:选择带[ ],.loc和.iloc
这是关于如何从pandas DataFrame或Series中选择数据子集的四部分系列的开始。Pandas为子集选择提供了多种选择,这需要多篇文章。本系列分为以下四个主题。
- 选择带[],.loc和.iloc
- 布尔索引
- 分配数据子集
- 如何不选择数据子集
开始之前的假设
这些系列文章假定您不了解Pandas,但是您了解Python编程语言的基础。它还假定您已在计算机上安装了Pandas。
将Pandas与Python和其他主要科学计算库结合使用的最简单方法是安装Miniconda发行版(请参阅完整的教程的链接)。
进行子集选择的重要性
您可能想知道,为什么有那么多关于选择数据子集的文章。这个主题对pandas来说非常重要,很遗憾它很复杂,因为在实际分析中子集选择经常发生。由于您经常选择子集,因此需要掌握它才能使pandas变得更轻松。
参考文档
有关索引和选择数据的官方pandas文档也涵盖了本文中的材料。我强烈建议您与本教程一起阅读文档的该部分。实际上,文档是掌握pandas的主要手段之一。我写了一篇循序渐进的文章“ 如何学习pandas”,其中提供了有关如何在掌握pandas的同时使用文档的建议。
DataFrame和Series的剖析
pandas库具有两个主要的数据容器:DataFrame和Series。使用Pandas时,几乎所有的时间都花在处理这两个对象上。DataFrame的使用比Series更多,因此让我们首先看一下它的图像。
此图像带有一些附加的插图,以突出显示其组件。乍一看,DataFrame看起来就像您看到的任何其他二维数据表一样。它有行,有列。从技术上讲,DataFrame具有三个主要组件。
DataFrame的三个组成部分
DataFrame由三个不同的组件组成:索引,列和数据。数据也称为值。
索引表示DataFrame最左侧的值序列。索引中的所有值都在粗字体。索引的每个单独的值称为标签。有时,该索引称为行标签。在上面的示例中,行标签不是很有趣,只是从0到n-1的整数,其中n是表中的行数。pandas默认使用此简单索引作为DataFrames。
这些列是DataFrame顶部的值序列。它们也以粗体显示。列的每个单独的值都称为列,但也可以称为列名或列标签。
其他所有非粗体字都是数据或值。有时您会听到被称为表格数据的DataFrames 。这只是具有行和列的矩形表数据的另一个名称。将行或列称为轴也是常见的术语。统称为“ 轴”。因此,一行是一个轴,一列是另一个轴。
每行都有一个标签,每列都有一个标签
从DataFrame解剖结构中得出的主要结论是,每行都有一个标签,每列都有一个标签。这些标签用于引用DataFrame中的特定行或列。这与人类如何使用名称来指代特定的人一样。
什么是子集选择?
在开始选择子集之前,最好定义一下子集。子集选择只是从DataFrame(或Series)中选择数据的特定行和列。这可能意味着选择所有行和一些列,选择一些行和所有列,或者选择每个行和列。
选择某些列和所有行的示例
让我们看一些子集选择的图像。我们将首先查看带有伪数据的示例DataFrame。
比方说,我们要选择的只是列color,age和height但保留所有行。
我们最终的DataFrame如下所示:
选择一些行和所有列的示例
我们还可以进行选择,仅选择一些行。我们选择带有标签的行Aaron,并Dean连同所有的列:
我们最终的DataFrame希望:
选择一些行和一些列的示例
让我们从上面结合选择和选择的列color,age以及height只带标签的行Aaron和Dean。
我们最终的DataFrame如下所示:
熊猫双重参考:按标签和按整数位置
我们已经提到过,每一行和每一列都有一个可用来引用它们的特定标签。这在DataFrame中以粗体显示。
但是,没有提到的是,每一行和每一列也可以由整数引用。我称这个整数位置。对于每一行和每一列,整数位置从0开始,以n-1结束。再次在上方查看我们的示例DataFrame。
带标签的行Aaron和Dean还可以通过它们各自的整数位置2和4类似地,列中引用color,age并且height可以通过它们的整数位置1,图3和4中被引用。
该文档将整数位置称为position。我不特别喜欢这种术语,因为它不像整数位置那样明确。这里的关键术语是整数。
索引和选择数据子集有什么区别?
该文档经常使用术语索引。这个术语本质上只是一个单字短语,用来表示“子集选择”。我更喜欢术语子集选择,因为它再次描述了实际发生的事情。索引也是官方Python文档中使用的术语。
只注重[],.loc以及.iloc
选择数据子集的方法有很多,但是在本文中,我们仅介绍方括号([])**.loc**和的用法**.iloc**。它们统称为索引器。到目前为止,这些是选择数据的最常用方法。本系列的不同部分将讨论一些可用于进行子集选择的方法。
如果您有一个DataFrame,则df您的子集选择将类似于以下内容:
df []
df.loc []
df.iloc []
实际的子集选择将在方括号内包含一些内容。本文中的所有选择都将在这些方括号内进行。
请注意,方括号也位于.loc和之后.iloc。Python中的所有索引都发生在这些方括号内。
使用以下命令将数据读入DataFrame read_csv
让我们开始使用熊猫读取DataFrame,然后从那里单独使用索引运算符选择数据子集。这些教程的所有数据都在数据目录中。
我们将使用该read_csv 函数将数据读入DataFrame。我们将路径传递到文件作为函数的第一个参数。我们还将使用该index_col`参数选择数据的第一列作为索引(稍后会对此进行更多介绍)。
>>> import pandas as pd
>>> import numpy as np>>> df = pd.read_csv('data/sample_data.csv', index_col=0)
>>> df
提取单个DataFrame组件
之前,我们提到了DataFrame的三个组件。索引,列和数据(值)。我们可以将每个组件提取到它们自己的变量中。让我们这样做,然后检查它们:
>>> index = df.index
>>> columns = df.columns
>>> values = df.values
>>> index
Index(['Jane', 'Niko', 'Aaron', 'Penelope', 'Dean', 'Christina',
'Cornelia'], dtype='object')
>>> columns
Index(['state', 'color', 'food', 'age', 'height', 'score'],
dtype='object')
>>> values
array([['NY', 'blue', 'Steak', 30, 165, 4.6],
['TX', 'green', 'Lamb', 2, 70, 8.3],
['FL', 'red', 'Mango', 12, 120, 9.0],
['AL', 'white', 'Apple', 4, 80, 3.3],
['AK', 'gray', 'Cheese', 32, 180, 1.8],
['TX', 'black', 'Melon', 33, 172, 9.5],
['TX', 'red', 'Beans', 69, 150, 2.2]], dtype=object)
组件的数据类型
让我们输出每个组件的类型,以准确了解它们是什么类型的对象。
>>> type(index)
pandas.core.indexes.base.Index
>>> type(columns)
pandas.core.indexes.base.Index
>>> type(values)
numpy.ndarray
了解这些类型
有趣的是,索引和列都是同一类型。它们都是pandasIndex对象。该对象本身功能非常强大,但是现在您可以将其视为行或列的标签序列。
这些值是NumPy `ndarray,代表n维数组,并且是NumPy库中数据的主要容器。Pandas直接建立在NumPy之上,正是这个数组负责大部分工作量。
从DataFrames上的索引运算符开始
Selecting a single column as a Series
我们将仅通过在DataFrame上使用索引运算符来开始选择子集的过程。其主要目的是选择单列或多列数据。
>>> df['food']
Jane Steak
Niko Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
系列(Series)解剖
选择单列数据将返回另一个pandas数据容器系列。系列是标记数据的一维序列。系列有两个主要组成部分,即索引和数据(或值)。系列中没有列。
系列的视觉显示只是纯文本,而不是DataFrames的样式表。左边的人名的顺序是索引。右边的实例顺序是数值。
您还将在系列底部注意到另外两个数据。系列的名称变为旧列名称。您还将看到数据类型或**dtype**系列数据。您现在可以忽略这两个项目。
选择多个列将返回一个DataFrame
选择多个列将返回一个DataFrame。实际上,您可以选择一个列作为具有一个项目列表的DataFrame:
df [['food']]
尽管这与上面的Series很像,但从技术上讲它是一个DataFrame,是一个不同的对象。
列顺序无关紧要
选择多个列时,可以按选择的任何顺序选择它们。它的顺序不必与原始DataFrame相同。例如,让我们选择height和color。
`df [['height','color']]`
例外情况
仅使用索引运算符进行选择时,会出现几个常见的例外。
- 如果您拼错一个单词,则会得到一个 **KeyError**
- 如果您忘记使用列表包含多个列,则还会得到一个 **KeyError**
>>> df['hight']
KeyError: 'hight'
>>> df['color', 'age'] # should be: df[['color', 'age']]
KeyError: ('color', 'age')
索引运算符总结
- 其主要目的是通过列名选择列
- 通过直接将列名传递给它,选择一个列作为“系列”: **df['col_name']**
- 通过将列表传递给它来选择多个列作为DataFrame :**df[['col_name1', 'col_name2']]**
- 您实际上可以选择带有它的行,但是由于它很混乱并且不经常使用,因此此处不会显示。
入门 .loc
该**.loc**索引中选择不仅仅是索引操作方式不同的数据。它可以选择行或列的子集。它还可以同时选择行和列的子集。最重要的是,它仅根据行和列的标签选择数据。
选择一行作为具有 .loc
**.loc**当给定单行标签时,索引器将返回一行作为系列。让我们选择的行**Niko**。
>>> df.loc['Niko']
state TX
color green
food Lamb
age 2
height 70
score 8.3
Name: Niko, dtype: object
选择多个行作为DataFrame与 .loc
要选择多行,请将您要选择的所有行标签放在列表中,然后将其传递给**.loc**。让我们选择Niko和Penelope。
>>> df.loc [['Niko','Penelope']]
使用切片符号选择带有 .loc
可以.loc通过使用切片符号来“切片” DataFrame的行。切片符号使用冒号分隔开始,停止和步进值。例如,我们可以选择所有的行Niko经过Dean是这样的:
>>> df.loc ['Niko':'Dean']
.loc 包括带有切片符号的最后一个值
请注意,标有的行Dean已保留。在其他数据容器(如Python列表)中,最后一个值被排除。
其他切片
您可以像使用列表一样使用切片符号。让我们从头开始切开Aaron:
>>> df.loc [:'Aaron']
>>> df.loc ['Niko':'Christina':2]
>>> df.loc ['Dean':]
### 同时选择行和列 .loc
与仅索引运算符不同,可以与同时选择行和列.loc。通过用逗号分隔行和列的选择来完成此操作。它看起来像这样:
>>> df.loc [行选择,列选择]
选择两行三列
举例来说,如果我们想要选择的行Dean和Cornelia与列一起age,state和score我们这样做:
>>> df.loc [['Dean','Cornelia'],['age','state','score']]
对行或列使用选择的任意组合 .loc
正如我们已经看到的,行或列的选择可以是以下任意一种:
- 单个标签
- 标签列表
- 带有标签的切片
我们可以使用来将这三个中的任何一个用于行或列选择**.loc**。让我们看一些例子。
让我们选择两行和一列:
>>> df.loc[['Dean', 'Aaron'], 'food']
Dean Cheese
Aaron Mango
Name: food, dtype: object
选择行的一部分和列的列表:
>>> df.loc ['Jane':'Penelope',['state','color']]
选择单行和单列。这将返回一个标量值
>>> df.loc ['Jane','age']
30
选择一片行和列
>>> df.loc [:'Dean','height':]
选择所有行和一些列
可以使用单个冒号选择所有行。然后,您可以照常选择列:
>>> df.loc [:, ['food','color']]
您还可以使用此表示法选择所有列:
>>> df.loc [['Penelope','Cornelia'],:]
但是,正如我们所见,这不是必需的,因此您可以省略最后一个冒号:
>>> df.loc [['Penelope','Cornelia']]
将行和列选择分配给变量
在使用之前,将行和列选择分配给变量可能会更容易.loc。如果要选择许多行或列,这将很有用:
>>> rows = ['Jane', 'Niko', 'Dean', 'Penelope', 'Christina']
>>> cols = ['state', 'age', 'height', 'score']
>>> df.loc[rows, cols]
总结 .loc
- 仅使用标签
- 可以同时选择行和列
- 选择内容可以是单个标签,标签列表或标签切片
- 在行和列选择之间放置逗号
入门 .iloc
该.iloc索引是非常相似的.loc,但只使用整数位置做出选择。该词.iloc本身代表整数位置,因此应有助于记住它的作用。
选择单行 .iloc
通过将单个整数传递给.iloc,它将选择一行作为系列:
>>> df.iloc[3]
state AL
color white
food Apple
age 4
height 80
score 3.3
Name: Penelope, dtype: object
使用选择多行 .iloc
使用整数列表选择多行:
>>> df.iloc[[5, 2, 4]] # remember, don't do df.iloc[5, 2, 4]
使用切片符号选择带有 .iloc
切片符号的作用类似于此实例中的列表,并且不包括最后一个元素
>>> df.iloc [3:5]
选择第三个位置直到结束:
>>> df.iloc [3:]
选择第3个位置以2为step结尾
>>> df.iloc [3 :: 2]
同时选择行和列 .iloc
就像.iloc单个整数的任何组合一样,整数或切片的列表可用于同时选择行和列。只需记住用逗号分隔选择即可。
选择两行两列:
>>> df.iloc [[2,3],[0,4]]
选择行和两列的一部分:
>>> df.iloc [3:6,[1,4]]
同时选择切片
>>> df.iloc [2:5,2:5]
选择单个行和列
>>> df.iloc [0,2]
'Steak'
选择所有行和单个列
>>> df.iloc[:, 5]
Jane 4.6
Niko 8.3
Aaron 9.0
Penelope 3.3
Dean 1.8
Christina 9.5
Cornelia 2.2
Name: score, dtype: float64
弃用 .ix
在pandas发展的早期,存在另一个索引器**ix**。该索引器能够通过标签和整数位置进行选择。尽管它用途广泛,但由于不明确,引起了很多混乱。有时,整数也可以作为行或列的标签。因此,在某些情况下它是模棱两可的。
您仍然可以拨打电话**.ix**,但是该电话已被弃用,因此请不要使用它。
选择系列子集
当然,我们也可以使用系列进行子集选择。早些时候,我建议仅使用索引运算符在DataFrame上进行列选择。由于Series没有列,我建议仅使用**.loc**和**.iloc**。您可以只使用索引运算符,但是它含糊不清,因为它可以同时使用标签和整数。在本教程的结尾,我将回到这一点。
通常,您将通过从DataFrame中选择单个列来创建一个Series。让我们选择**food**列:
>>> food = df['food']
>>> food
Jane Steak
Niko Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
系列选择 .loc
系列选择.loc非常简单,因为我们只处理一个维度。您可以再次使用单个行标签,行标签列表或行标签切片来进行选择。让我们看几个例子。
>>> food.loc ['Aaron']
'Mango'
选择三个不同的值。这将返回一个Series:
>>> food.loc[['Dean', 'Niko', 'Cornelia']]
Dean Cheese
Niko Lamb
Cornelia Beans
Name: food, dtype: object
切片从Niko到Christina-包括最后一个索引:
>>> food.loc['Niko':'Christina']
Niko Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Name: food, dtype: object
从头到尾切片Penelope:
>>> food.loc['Penelope':]
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
在列表中选择一个返回序列的值:
>>> food.loc[['Aaron']]
Aaron Mango
Name: food, dtype: object
系列选择 .iloc
序列子集的选择与**.iloc**发生类似,**.loc**只不过它使用整数位置。您可以使用单个整数,整数列表或整数切片。让我们看一些例子。
选择一个值:
>>> food.iloc[0]
'Steak'
使用整数列表选择多个值:
>>> food.iloc[[4, 1, 3]]
Dean Cheese
Niko Lamb
Penelope Apple
Name: food, dtype: object
使用切片-不包括最后一个整数
>>> food.iloc[4:6]
Dean Cheese
Christina Melon
Name: food, dtype: object
与Python列表和字典的比较
将pandas根据标签和整数位置进行选择的能力与Python列表和字典的选择能力进行比较可能会有所帮助。
Python列表仅允许通过整数位置选择数据。
您可以使用单个整数或切片符号来进行选择,但不能使用整数列表。
让我们看一下使用整数的列表子集选择的示例:
>>> some_list = ['a','two',10,4,0,'asdf','mgmt',
434,99
]
>>> some_list [5]
'asdf'
>>> some_list [-1]
99
>>> some_list [:4]
['a','two',
10,4
]
>>> some_list [3:]
[
4,0
,'asdf','mgmt',
434,99
]
>>> some_list [2:6:3]
[10,'asdf']
使用Python字典按标签选择
每个字典中的所有值都用键标记。
我们使用此键进行单个选择。词典仅允许使用单个标签进行选择。标签的切片和列表均不允许。
>>> d = {'a':1,'b':2,'t':20,'z':26,'A':27}
>>> d ['a']
1
>>> d ['A']
27
pandas拥有名单和字典的权力
DataFrame和Series可以使用整数(如列表)和标签(如字典)进行选择。
仅使用索引运算符从DataFrame中选择行-令人困惑!
上面,我仅使用索引运算符从DataFrame中选择一列或多列。但是,它也可以用于使用slice选择行。我认为这种行为非常令人困惑。传递切片时,整个操作将完全更改。
让我们使用整数切片作为第一个示例:
>>> df [3:6]
了增加这种混乱,您还可以按标签切片。
>>> df ['Aaron':'Christina']
我建议不要这样做!
此功能不会被弃用,并且完全取决于您是否要使用它。但是,我非常希望不要以这种方式选择行,因为这样可能会造成歧义,尤其是在索引中包含整数的情况下。
使用**.iloc**和**.loc**是明确的,可以清楚地告诉阅读代码的人将会发生什么。让我们使用**.iloc**和重写上面的内容**.loc**。
>>> df.iloc[3:6] # More explicit that df[3:6]
>>> df.loc['Aaron':'Christina']
不能同时选择行和列 []
如果尝试仅使用索引运算符同时选择行和列,则会引发异常。您必须使用**.loc**或**.iloc**这样做。
>>> df[3:6, 'Aaron':'Christina']
TypeError: unhashable type: 'slice'
仅使用索引运算符从系列中选择行-令人困惑!
您也可以仅将索引运算符与系列一起使用。同样,这令人困惑,因为它可以接受整数或标签。让我们看一些例子
>>> food
Jane Steak
Niko Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object>>> food[2:4]
Aaron Mango
Penelope Apple
Name: food, dtype: object>>> food['Niko':'Dean']
Niko Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Name: food, dtype: object
Since Series don’t have columns you can use a single label and list of labels to make selections as well
>>> food['Dean']
'Cheese'>>> food[['Dean', 'Christina', 'Aaron']]
Dean Cheese
Christina Melon
Aaron Mango
Name: food, dtype: object
Again, I recommend against doing this and always use **.iloc** or **.loc**
我建议您不要这样做,请始终使用**.iloc**或**.loc**
导入数据而不选择索引列
我们通过选择第一列作为带有函数**index_col**参数的索引来导入数据**read_csv**。通常,这不是将大多数DataFrame读入pandas的方式。
通常,csv文件中的所有列都将成为DataFrame列。熊猫将使用0到n-1之间的整数作为标签。请参见下面的示例数据,其中的数据集略有不同:
>>> df2 = pd.read_csv('data / sample_data2.csv')
>>> df2
默认值 RangeIndex
如果您在第一次读取数据时未将列指定为索引,则熊猫将使用0到n-1之间的整数作为索引。从技术上讲,这会创建一个**RangeIndex**对象。让我们来看看它。
>>> df2.index
RangeIndex(start=0, stop=7, step=1)
This object is similar to Python **range** objects. Let's create one:
>>> range(7)
range(0, 7)
Converting both of these objects to a list produces the exact same thing:
>>> list(df2.index)
[0, 1, 2, 3, 4, 5, 6]
>>> list(range(7))
[0, 1, 2, 3, 4, 5, 6]
目前,拥有一点都不重要**RangeIndex**。与**.loc**和的选择相同**.iloc**。让我们看一些例子。
df2.loc [[2,4,5],['food','color']]
>>> df2.iloc [[2,4,5],[3,2]]
使用切片时有细微的差别。**.iloc**排除最后一个值,而**.loc**包括它:
>>> df2.iloc [:3]`
>>> df2.loc [:3]
读取数据后从列设置索引
常见的情况是看到熊猫代码读取带有RangeIndex的DataFrame,然后将索引设置为列之一。通常使用以下**set_index**方法完成此操作:
>>> df2_idx = df2.set_index('Names')
>>> df2_idx
索引有一个名字
请注意,此DataFrame与本教程开头的第一个看起来并不完全相同。索引正上方是黑体字**Names**。从技术上讲,这是索引的名称。我们原始的DataFrame没有为其索引命名。您现在可以忽略此小细节。子集选择将以相同的方式发生。
带点表示法的DataFrame列选择
Pandas允许您使用点符号选择一个列作为“系列” 。这也称为属性访问。您只需将列名放在圆点和DataFrame之后,而不用引号,如下所示:
>>> df.state
Jane NY
Niko TX
Aaron FL
Penelope AL
Dean AK
Christina TX
Cornelia TX
Name: state, dtype: object
>>> df.age
Jane 30
Niko 2
Aaron 12
Penelope 4
Dean 32
Christina 33
Cornelia 69
Name: age, dtype: int64
通过属性访问选择列的利弊
选择这样的列的最大好处是,在选择后链接方法时会获得帮助。例如,如果您在列名后放置另一个点并按tab,则所有Series方法的列表将出现在弹出菜单中。它看起来像这样:
仅使用索引运算符时,此帮助将消失:
最大的缺点是您不能选择空格或其他字符无效的列作为Python标识符(变量名)。
选择两次相同的列?
这很奇怪,但是实际上您可以多次选择同一列:
df [['age','age','age']]
pandas总结概述
我们涵盖了不可思议的领域。让我们总结所有要点:
- 在学习pandas之前,请确保您具有Python的基础知识
- 学习新的pandas操作时请始终参考文档
- DataFrame和Series是数据的容器
- DataFrame是二维的表格数据
- 系列是数据的一个维度
- DataFrame的三个组成部分是索引,列和数据(或值)
- 标签和整数位置都引用DataFrame的每一行和每一列
- 有三种主要的方法从数据框中选择的子集- **[]**,**.loc**和**.iloc**
- 我仅使用索引运算符一词来指代**[]**紧随DataFrame / Series之后的术语
- 索引运算符的主要目的只是从DataFrame中选择一列或多列
- 仅对索引运算符使用单个列名称,就将一个数据列作为系列返回
- 将列表中的多个列传递给仅索引运算符将返回一个DataFrame
- 系列有两个组成部分,索引和数据(值)。它没有列
- **.loc**仅按标签进行选择
- **.loc** 可以同时选择行和列
- **.loc** 可以使用单个标签,标签列表或标签切片进行选择
- **.loc** 首先进行行选择,然后进行列选择: **df.loc[row_selection, col_selection]**
- **.iloc**类似于。**loc**但仅使用整数位置来引用行或列。
- **.ix** 已弃用,永远不要使用
- **.loc**和**.iloc**Series一样,除了它们没有索引,只根据索引选择
- Pandas结合了python列表(通过整数位置选择)和字典(通过标签选择)的功能
- 您可以只使用索引运算符从DataFrame中选择行,但是我建议您反对这样做,而应坚持使用显式**.loc**和**.iloc**
- 通常,数据导入时无需设置索引。使用该**set_index**方法可以将列用作索引。
- 您可以从带点标记的DataFrame中选择一个列作为Series
本文转载自:好好先生,如有侵权请联系删除
知乎原文链接:好好先生:Pandas 操作数据集(最全总结之一)