AZh*_*hao 574 python indexing dataframe pandas
有人能解释这三种切片方法有何不同?
我已经看过这些文档了,我已经看到了这些 答案,但我仍然发现自己无法解释三者是如何不同的.对我来说,它们在很大程度上似乎是可以互换的,因为它们处于较低的切片水平.
例如,假设我们想获得a的前五行DataFrame
.这三个都是如何运作的?
df.loc[:5]
df.ix[:5]
df.iloc[:5]
Run Code Online (Sandbox Code Playgroud)
有人可以提出三种情况,其中使用的区别更清晰吗?
Ale*_*ley 885
注:在大熊猫版本0.20.0及以上,ix
被弃用和使用loc
,并iloc
改为鼓励.我已经将这个答案的部分内容ix
完整地描述为早期版本的pandas用户的参考.下面添加了示例,显示了替代方案 ix
.
首先,这里是三种方法的概述:
loc
获取索引中具有特定标签的行(或列).iloc
获取索引中特定位置的行(或列)(因此它只需要整数).ix
通常尝试表现得像loc
但是回退到表现如同iloc
索引中不存在标签.重要的是要注意一些可能使用起来ix
有些棘手的细微之处:
如果索引是整数类型,ix
则只使用基于标签的索引,而不是回退到基于位置的索引.如果标签不在索引中,则会引发错误.
如果指数不包含唯一整数,然后给出一个整数,ix
将立即使用基于位置的索引,而不是基于标签的索引.但是,如果ix
给出另一种类型(例如字符串),则可以使用基于标签的索引.
为了说明这三种方法之间的差异,请考虑以下系列:
>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
4 NaN
5 NaN
Run Code Online (Sandbox Code Playgroud)
我们将看一下整数值的切片3
.
在这种情况下,s.iloc[:3]
返回前3行(因为它将3视为一个位置)并s.loc[:3]
返回前8行(因为它将3视为标签):
>>> s.iloc[:3] # slice the first three rows
49 NaN
48 NaN
47 NaN
>>> s.loc[:3] # slice up to and including label 3
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
Run Code Online (Sandbox Code Playgroud)
注意s.ix[:3]
返回相同的Series,s.loc[:3]
因为它首先查找标签而不是处理位置(并且s
is是整数类型的索引).
如果我们尝试使用不在索引中的整数标签(比方说6
)怎么办?
这里s.iloc[:6]
按预期返回系列的前6行.但是,s.loc[:6]
由于6
不在索引中,因此会引发KeyError .
>>> s.iloc[:6]
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
>>> s.loc[:6]
KeyError: 6
>>> s.ix[:6]
KeyError: 6
Run Code Online (Sandbox Code Playgroud)
根据上面提到的细微之处,s.ix[:6]
现在引发了一个KeyError,因为它试图像在索引中loc
找不到一样但却找不到它6
.因为我们的索引是整数类型,ix
所以不会回归到像iloc
.
但是,如果我们的索引是混合类型,给定一个整数ix
会iloc
立即表现而不是引发KeyError:
>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a NaN
b NaN
c NaN
d NaN
e NaN
1 NaN
Run Code Online (Sandbox Code Playgroud)
请记住,ix
仍然可以接受非整数并且表现得像loc
:
>>> s2.ix[:'c'] # behaves like loc given non-integer
a NaN
b NaN
c NaN
Run Code Online (Sandbox Code Playgroud)
作为一般建议,如果您只使用标签进行索引,或仅使用整数位置进行索引,请坚持loc
或iloc
避免出现意外结果 - 请勿使用ix
.
有时给定一个DataFrame,您需要为行和列混合标签和位置索引方法.
例如,请考虑以下DataFrame.如何最好地将行切割到包括'c' 并包含前四列?
>>> df = pd.DataFrame(np.nan,
index=list('abcde'),
columns=['x','y','z', 8, 9])
>>> df
x y z 8 9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
在早期版本的pandas中(在0.20.0之前)ix
让你可以非常巧妙地做到这一点 - 我们可以按标签切片行,按位置切片列(请注意,对于列,ix
默认为基于位置的切片,因为 4
它不是列名):
>>> df.ix[:'c', :4]
x y z 8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
在后续版本的pandas中,我们可以使用iloc
另一种方法帮助实现此结果:
>>> df.iloc[:df.index.get_loc('c') + 1, :4]
x y z 8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
get_loc()
是一种索引方法,意思是"获取此索引中标签的位置".请注意,由于切片iloc
与其端点不同,如果我们还想要行'c',我们必须将1加到此值.
有在大熊猫的文档进一步的例子在这里.
Joe*_*ron 129
iloc
基于整数定位.因此,无论您的行标签是什么,您都可以随时获取第一行
df.iloc[0]
Run Code Online (Sandbox Code Playgroud)
或者做最后五行
df.iloc[-5:]
Run Code Online (Sandbox Code Playgroud)
您也可以在列上使用它.这将检索第3列:
df.iloc[:, 2] # the : in the first position indicates all rows
Run Code Online (Sandbox Code Playgroud)
您可以将它们组合在一起以获得行和列的交集:
df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)
Run Code Online (Sandbox Code Playgroud)
另一方面,.loc
使用命名索引.让我们设置一个数据框,其中包含字符串作为行标签和列标签:
df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])
Run Code Online (Sandbox Code Playgroud)
然后我们可以得到第一行
df.loc['a'] # equivalent to df.iloc[0]
Run Code Online (Sandbox Code Playgroud)
和第二两排的'date'
柱通过
df.loc['b':, 'date'] # equivalent to df.iloc[1:, 1]
Run Code Online (Sandbox Code Playgroud)
等等.现在,值得指出的是,a的默认行和列索引DataFrame
是从0开始的整数,在这种情况下iloc
,它们loc
将以相同的方式工作.这就是为什么你的三个例子是等价的.如果您有一个非数字索引,如字符串或日期时间, df.loc[:5]
将引发错误.
此外,您只需使用数据框即可进行列检索__getitem__
:
df['time'] # equivalent to df.loc[:, 'time']
Run Code Online (Sandbox Code Playgroud)
现在假设您要混合位置和命名索引,即使用行上的名称和列上的位置进行索引(澄清一下,我的意思是从我们的数据框中选择,而不是在行索引和整数中创建一个包含字符串的数据框)列索引).这是.ix
进来的地方:
df.ix[:2, 'time'] # the first two rows of the 'time' column
Run Code Online (Sandbox Code Playgroud)
我认为值得一提的是你也可以将布尔向量传递给loc
方法.例如:
b = [True, False, True]
df.loc[b]
Run Code Online (Sandbox Code Playgroud)
将返回第1行和第3行df
.这相当于df[b]
选择,但它也可以用于通过布尔向量进行赋值:
df.loc[b, 'name'] = 'Mary', 'John'
Run Code Online (Sandbox Code Playgroud)
Ted*_*rou 102
在我看来,接受的答案令人困惑,因为它使用只有缺失值的DataFrame.我也不喜欢这个词,基于位置的.iloc
,相反,喜欢整数位置,因为它是更描述性,正是.iloc
代表.关键词是INTEGER - .iloc
需要INTEGERS.
有关详细信息,请参阅我关于子集选择的非常详细的博
因为.ix
已弃用,我们只关注.loc
和之间的差异.iloc
.
在我们讨论差异之前,重要的是要了解DataFrames的标签有助于识别每个列和每个索引.我们来看一个示例DataFrame:
df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
'height':[165, 70, 120, 80, 180, 172, 150],
'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
},
index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])
Run Code Online (Sandbox Code Playgroud)
所有粗体字都是标签.标签,age
,color
,food
,height
,score
和state
被用于列.其他标签,Jane
,Nick
,Aaron
,Penelope
,Dean
,Christina
,Cornelia
被用于索引.
在DataFrame中选择特定行的主要方法是使用.loc
和.iloc
索引器.这些索引器中的每一个也可用于同时选择列,但现在更容易关注行.此外,每个索引器都使用一组括号,这些括号紧跟其名称后进行选择.
我们将首先讨论.loc
仅通过索引或列标签选择数据的索引器.在我们的示例DataFrame中,我们提供了有意义的名称作为索引的值.许多DataFrames没有任何有意义的名称,而是默认只有从0到n-1的整数,其中n是DataFrame的长度.
您可以使用三种不同的输入 .loc
使用带字符串的.loc选择单行
要选择单行数据,请将索引标签放在以下括号内.loc
.
df.loc['Penelope']
Run Code Online (Sandbox Code Playgroud)
这会将数据行作为Series返回
age 4
color white
food Apple
height 80
score 3.3
state AL
Name: Penelope, dtype: object
Run Code Online (Sandbox Code Playgroud)
使用带有字符串列表的.loc选择多行
df.loc[['Cornelia', 'Jane', 'Dean']]
Run Code Online (Sandbox Code Playgroud)
这将返回一个DataFrame,其中的行按列表中指定的顺序排列:
使用切片表示法选择带有.loc的多行
切片表示法由开始,停止和步骤值定义.按标签切片时,pandas在返回时包含停止值.以下切片从Aaron到Dean,包括在内.其步长未明确定义,但默认为1.
df.loc['Aaron':'Dean']
Run Code Online (Sandbox Code Playgroud)
复杂切片可以采用与Python列表相同的方式.
我们现在转向.iloc
.DataFrame中的每一行和每列数据都有一个定义它的整数位置.这是在输出中以可视方式显示的标签的补充.整数位置只是从0开始的顶部/左侧的行数/列数.
您可以使用三种不同的输入 .iloc
使用带整数的.iloc选择单行
df.iloc[4]
Run Code Online (Sandbox Code Playgroud)
这将返回第5行(整数位置4)作为系列
age 32
color gray
food Cheese
height 180
score 1.8
state AK
Name: Dean, dtype: object
Run Code Online (Sandbox Code Playgroud)
使用带有整数列表的.iloc选择多行
df.iloc[[2, -2]]
Run Code Online (Sandbox Code Playgroud)
这将返回第三行和第二行到最后一行的DataFrame:
使用切片表示法选择带有.iloc的多行
df.iloc[:5:3]
Run Code Online (Sandbox Code Playgroud)
两者的一个优秀能力.loc/.iloc
是它们能够同时选择行和列.在上面的示例中,从每个选择中返回所有列.我们可以选择具有与行相同类型输入的列.我们只需要用逗号分隔行和列选择.
例如,我们可以选择行Jane,而Dean只选择列高度,分数和状态,如下所示:
df.loc[['Jane', 'Dean'], 'height':]
Run Code Online (Sandbox Code Playgroud)
这使用行的标签列表和列的切片表示法
我们可以自然地.iloc
只使用整数来执行类似的操作.
df.iloc[[1,4], 2]
Nick Lamb
Dean Cheese
Name: food, dtype: object
Run Code Online (Sandbox Code Playgroud)
.ix
用于与标签和整数位置同时进行选择,这有时令人困惑和含糊不清,谢天谢地它已被弃用.如果您需要使用混合标签和整数位置进行选择,则必须同时选择标签或整数位置.
例如,如果我们想要选择行Nick
以及第Cornelia
2列和第4列,我们可以.loc
通过将整数转换为带有以下内容的标签来使用:
col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names]
Run Code Online (Sandbox Code Playgroud)
或者,使用get_loc
索引方法将索引标签转换为整数.
labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]
Run Code Online (Sandbox Code Playgroud)
.loc索引器也可以进行布尔选择.例如,如果我们有兴趣找到年龄超过30的所有行并返回food
和score
列,我们可以执行以下操作:
df.loc[df['age'] > 30, ['food', 'score']]
Run Code Online (Sandbox Code Playgroud)
您可以复制它,.iloc
但不能将它传递给布尔系列.您必须将布尔系列转换为numpy数组,如下所示:
df.iloc[(df['age'] > 30).values, [2, 4]]
Run Code Online (Sandbox Code Playgroud)
可以.loc/.iloc
仅用于列选择.您可以使用冒号选择所有行,如下所示:
df.loc[:, 'color':'score':2]
Run Code Online (Sandbox Code Playgroud)
[]
也可以选择行和列,但不能同时选择.大多数人都熟悉DataFrame索引操作符的主要用途,即选择列.字符串选择单个列作为Series,字符串列表选择多个列作为DataFrame.
df['food']
Jane Steak
Nick Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
Run Code Online (Sandbox Code Playgroud)
使用列表选择多个列
df[['food', 'score']]
Run Code Online (Sandbox Code Playgroud)
人们不太熟悉的是,当使用切片表示法时,则通过行标签或整数位置进行选择.这非常混乱,我几乎从不使用它,但它确实有效.
df['Penelope':'Christina'] # slice rows by label
Run Code Online (Sandbox Code Playgroud)
df[2:6:2] # slice rows by integer location
Run Code Online (Sandbox Code Playgroud)
.loc/.iloc
选择行的明确性是非常优选的.单独的索引操作符无法同时选择行和列.
df[3:5, 'color']
TypeError: unhashable type: 'slice'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
415675 次 |
最近记录: |