要选择第 i
行,使用 iloc
:
In [31]: df_test.iloc[0]
Out[31]:
ATime 1.2
X 2.0
Y 15.0
Z 2.0
Btime 1.2
C 12.0
D 25.0
E 12.0
Name: 0, dtype: float64
要选择Btime
列中的第i个值,你可以使用:
In [30]: df_test['Btime'].iloc[0]
Out[30]: 1.2
df_test['Btime'].iloc[0]
(推荐)和df_test.iloc[0]['Btime']
之间存在差异:
DataFrames以列为基础块存储数据(每个块具有单个dtype)。如果您首先按列选择,则可能返回视图(比返回副本更快),并且原始dtype得到保留。相反,如果您首先按行选择,并且DataFrame具有不同dtype的列,则Pandas会将数据复制到新的对象dtype系列中。因此,选择列比选择行稍快。因此,尽管df_test.iloc[0]['Btime']
有效,但df_test['Btime'].iloc[0]
更加高效。
在分配方面,两者之间存在很大差异。df_test['Btime'].iloc[0] = x
会影响df_test
,但df_test.iloc[0]['Btime']
可能不会。请参见下面的解释。由于索引顺序的微小差异会导致行为上的重大差异,因此最好使用单个索引分配:
df.iloc[0, df.columns.get_loc('Btime')] = x
df.iloc[0, df.columns.get_loc('Btime')] = x
(推荐):
向DataFrame分配新值的推荐方法是避免链式索引,而是使用andrew所示的方法。
df.loc[df.index[n], 'Btime'] = x
或者
df.iloc[n, df.columns.get_loc('Btime')] = x
后一种方法速度较快,因为
df.loc
需要将行和列标签转换为位置索引,如果使用
df.iloc
,则需要进行的转换较少。
df['Btime'].iloc[0] = x
能够运行,但不建议使用:
虽然这个方法可以运行,但它利用了DataFrame当前的实现方式。未来Pandas并不保证一定会继续这样工作。特别地,它利用了当前的df['Btime']
总是返回视图(而不是副本)的事实,因此可以使用df['Btime'].iloc[n] = x
在df
的Btime
列的第n个位置上赋值一个新值。
由于Pandas没有明确保证索引器何时返回视图而不是副本,因此即使在这种情况下赋值成功修改了df
,使用链式索引的赋值通常仍会引发SettingWithCopyWarning
警告:
In [22]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [24]: df['bar'] = 100
In [25]: df['bar'].iloc[0] = 99
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self._setitem_with_indexer(indexer, value)
In [26]: df
Out[26]:
foo bar
0 A 99 <-- assignment succeeded
2 B 100
1 C 100
df.iloc[0]['Btime'] = x
不起作用:
相反,使用 df.iloc[0]['bar'] = 123
进行赋值也不起作用,因为 df.iloc[0]
返回的是一个副本:
In [66]: df.iloc[0]['bar'] = 123
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
In [67]: df
Out[67]:
foo bar
0 A 99 <-- assignment failed
2 B 100
1 C 100
警告: 我之前建议使用 df_test.ix[i, 'Btime']
。但是这不能保证给出第i
行的值,因为ix
会先尝试按标签进行索引,然后再尝试按位置进行索引。所以,如果DataFrame具有未从0开始排序的整数索引,则使用ix[i]
将返回标记为i
的行,而不是第i
行。例如,
In [1]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [2]: df
Out[2]:
foo
0 A
2 B
1 C
In [4]: df.ix[1, 'foo']
Out[4]: 'C'
df_test.iloc[0]['Btime']
可行,但df_test.iloc['Btime'][0]
更加高效。 - unutbu