索引 Pandas 个数据框:整数行,命名列
Indexing Pandas data frames: integer rows, named columns
说 df
是一个 pandas 数据框。
df.loc[]
只接受名字
df.iloc[]
只接受整数(实际放置)
df.ix[]
接受名称和整数:
引用行时,df.ix[row_idx, ]
只想给出名称。例如
df = pd.DataFrame({'a' : ['one', 'two', 'three','four', 'five', 'six'],
'1' : np.arange(6)})
df = df.ix[2:6]
print(df)
1 a
2 2 three
3 3 four
4 4 five
5 5 six
df.ix[0, 'a']
抛出一个错误,它没有给出 return 'two'。
引用列时,iloc 更喜欢整数,而不是名称。例如
df.ix[2, 1]
returns 'three',不是 2。(尽管 df.idx[2, '1']
确实 return 2
)。
奇怪的是,我想要完全相反的功能。通常我的列名很有意义,所以在我的代码中我直接引用它们。但是由于大量观察清理,我的 pandas 数据框中的行名称通常不对应 range(len(df))
。
我意识到我可以使用:
df.iloc[0].loc['a'] # returns three
不过好像很难看!有谁知道更好的方法来做到这一点,以便代码看起来像这样?
df.foo[0, 'a'] # returns three
事实上,是否可以将我自己的新方法添加到 pandas.core.frame.DataFrame
s,例如
df.idx(rows, cols)
实际上是 df.iloc[rows].loc[cols]
?
这是一个迟到的答案,但@unutbu 的评论仍然有效,并且是解决此问题的好方法。
使用整数行和命名列(标记列)索引 DataFrame:
df.loc[df.index[#], 'NAME']
其中 #
是有效的整数索引,NAME
是列的名称。
我们可以重置索引,然后像这样使用基于 0 的索引
df.reset_index(drop=True).loc[0,'a']
编辑:从列名称索引 'a'
中删除了 []
,因此它只输出值
像 df["a"][0] 这样的东西对我来说工作正常。你可以试试看!
要在 DataFrame
by row/column 标签中获取或设置 单个 值,您最好按原样使用 DataFrame.at
instead of DataFrame.loc
。 ..
- 更快
- 您更明确地表示只想访问一个值。
其他人已经表明,如果您从行的整数位置开始,您仍然必须首先使用 DataFrame.index
找到行标签,因为 DataFrame.at
只接受标签:
df.at[df.index[0], 'a']
# Out: 'three'
基准:
%timeit df.at[df.index[0], 'a']
# 7.57 µs ± 30.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.loc[df.index[0], 'a']
# 10.9 µs ± 53.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.iloc[0, df.columns.get_loc("a")]
# 13.3 µs ± 24 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
完整性:
DataFrame.iat
用于按整数位置访问 row/column 对的单个值。
现有的答案对我来说似乎是短视的。
有问题的解决方案
df.loc[df.index[0], 'a']
这里的策略是获取第0行的行标签,然后照常使用.loc
。我看到两个问题。
- 如果
df
有重复的行标签,df.loc[df.index[0], 'a']
可以 return 多行。
.loc
比 .iloc
慢,所以你在这里牺牲了速度。
df.reset_index(drop=True).loc[0, 'a']
这里的策略是重置索引,使行标签变为 0、1、2,...因此 .loc[0]
给出与 .iloc[0]
相同的结果。尽管如此,这里的问题仍然是运行时,因为 .loc
比 .iloc
慢,并且您会产生重置索引的成本。
更好的解决方案
我建议关注 :
df.iloc[0, df.columns.get_loc("a")]
本质上,这与 df.iloc[0, 0]
相同,只是我们使用 df.columns.get_loc("a")
.
动态获取列索引
要索引多个列,例如 ['a', 'b', 'c']
,请使用:
df.iloc[0, [df.columns.get_loc(c) for c in ['a', 'b', 'c']]]
更新
这是讨论 here as part of my course on Pandas。
一个很晚的答案,但令我惊讶的是 pandas 这么多年了仍然没有这样的功能。如果它让你很烦,你可以将自定义索引器猴子修补到 DataFrame 中:
class XLocIndexer:
def __init__(self, frame):
self.frame = frame
def __getitem__(self, key):
row, col = key
return self.frame.iloc[row][col]
pd.core.indexing.IndexingMixin.xloc = property(lambda frame: XLocIndexer(frame))
# Usage
df.xloc[0, 'a'] # one
说 df
是一个 pandas 数据框。
df.loc[]
只接受名字df.iloc[]
只接受整数(实际放置)df.ix[]
接受名称和整数:
引用行时,df.ix[row_idx, ]
只想给出名称。例如
df = pd.DataFrame({'a' : ['one', 'two', 'three','four', 'five', 'six'],
'1' : np.arange(6)})
df = df.ix[2:6]
print(df)
1 a
2 2 three
3 3 four
4 4 five
5 5 six
df.ix[0, 'a']
抛出一个错误,它没有给出 return 'two'。
引用列时,iloc 更喜欢整数,而不是名称。例如
df.ix[2, 1]
returns 'three',不是 2。(尽管 df.idx[2, '1']
确实 return 2
)。
奇怪的是,我想要完全相反的功能。通常我的列名很有意义,所以在我的代码中我直接引用它们。但是由于大量观察清理,我的 pandas 数据框中的行名称通常不对应 range(len(df))
。
我意识到我可以使用:
df.iloc[0].loc['a'] # returns three
不过好像很难看!有谁知道更好的方法来做到这一点,以便代码看起来像这样?
df.foo[0, 'a'] # returns three
事实上,是否可以将我自己的新方法添加到 pandas.core.frame.DataFrame
s,例如
df.idx(rows, cols)
实际上是 df.iloc[rows].loc[cols]
?
这是一个迟到的答案,但@unutbu 的评论仍然有效,并且是解决此问题的好方法。
使用整数行和命名列(标记列)索引 DataFrame:
df.loc[df.index[#], 'NAME']
其中 #
是有效的整数索引,NAME
是列的名称。
我们可以重置索引,然后像这样使用基于 0 的索引
df.reset_index(drop=True).loc[0,'a']
编辑:从列名称索引 'a'
中删除了 []
,因此它只输出值
像 df["a"][0] 这样的东西对我来说工作正常。你可以试试看!
要在 DataFrame
by row/column 标签中获取或设置 单个 值,您最好按原样使用 DataFrame.at
instead of DataFrame.loc
。 ..
- 更快
- 您更明确地表示只想访问一个值。
其他人已经表明,如果您从行的整数位置开始,您仍然必须首先使用 DataFrame.index
找到行标签,因为 DataFrame.at
只接受标签:
df.at[df.index[0], 'a']
# Out: 'three'
基准:
%timeit df.at[df.index[0], 'a']
# 7.57 µs ± 30.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.loc[df.index[0], 'a']
# 10.9 µs ± 53.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.iloc[0, df.columns.get_loc("a")]
# 13.3 µs ± 24 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
完整性:
DataFrame.iat
用于按整数位置访问 row/column 对的单个值。
现有的答案对我来说似乎是短视的。
有问题的解决方案
df.loc[df.index[0], 'a']
这里的策略是获取第0行的行标签,然后照常使用.loc
。我看到两个问题。- 如果
df
有重复的行标签,df.loc[df.index[0], 'a']
可以 return 多行。 .loc
比.iloc
慢,所以你在这里牺牲了速度。
- 如果
df.reset_index(drop=True).loc[0, 'a']
这里的策略是重置索引,使行标签变为 0、1、2,...因此.loc[0]
给出与.iloc[0]
相同的结果。尽管如此,这里的问题仍然是运行时,因为.loc
比.iloc
慢,并且您会产生重置索引的成本。
更好的解决方案
我建议关注
df.iloc[0, df.columns.get_loc("a")]
本质上,这与 df.iloc[0, 0]
相同,只是我们使用 df.columns.get_loc("a")
.
要索引多个列,例如 ['a', 'b', 'c']
,请使用:
df.iloc[0, [df.columns.get_loc(c) for c in ['a', 'b', 'c']]]
更新
这是讨论 here as part of my course on Pandas。
一个很晚的答案,但令我惊讶的是 pandas 这么多年了仍然没有这样的功能。如果它让你很烦,你可以将自定义索引器猴子修补到 DataFrame 中:
class XLocIndexer:
def __init__(self, frame):
self.frame = frame
def __getitem__(self, key):
row, col = key
return self.frame.iloc[row][col]
pd.core.indexing.IndexingMixin.xloc = property(lambda frame: XLocIndexer(frame))
# Usage
df.xloc[0, 'a'] # one