我很困惑为什么在创建多列时括号[]和.loc表现不同。我已经研究了其他类似的问题,但是我找不到答案。
例如,
>>> dates = pd.date_range('1/1/2000', periods=8)
>>> df = pd.DataFrame(np.random.randn(8, 4), index=dates, columns=['A', 'B', 'C', 'D'])
>>> df
A B C D
2000-01-01 -1.011264 -1.751948 0.059012 0.514253
2000-01-02 0.596959 0.348866 -1.011628 0.950259
2000-01-03 0.305281 0.486400 -1.034534 -1.523402
2000-01-04 -0.880457 0.379837 2.023866 1.588379
2000-01-05 -1.142070 -0.168992 -0.391355 0.809820
2000-01-06 -0.335015 0.721563 -0.665120 -1.097811
2000-01-07 -0.160611 -0.601393 -0.257349 -0.830527
2000-01-08 0.197624 -0.082786 1.335873 -0.841006
如果我用方括号创建多个列,则其工作原理如下。
>>> df[['E','F']] = df[['A','B']]
>>> df
A B C D E F
2000-01-01 -1.011264 -1.751948 0.059012 0.514253 -1.011264 -1.751948
2000-01-02 0.596959 0.348866 -1.011628 0.950259 0.596959 0.348866
2000-01-03 0.305281 0.486400 -1.034534 -1.523402 0.305281 0.486400
2000-01-04 -0.880457 0.379837 2.023866 1.588379 -0.880457 0.379837
2000-01-05 -1.142070 -0.168992 -0.391355 0.809820 -1.142070 -0.168992
2000-01-06 -0.335015 0.721563 -0.665120 -1.097811 -0.335015 0.721563
2000-01-07 -0.160611 -0.601393 -0.257349 -0.830527 -0.160611 -0.601393
2000-01-08 0.197624 -0.082786 1.335873 -0.841006 0.197624 -0.082786
但是,如果我使用.loc方法创建多个列,则无法使用。
>>> df.loc[:,['H','I']] = df[['A','B']]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python\lib\site-packages\pandas\core\indexing.py", line 189, in __setitem__
indexer = self._get_setitem_indexer(key)
File "C:\Python\lib\site-packages\pandas\core\indexing.py", line 167, in _get_setitem_indexer
return self._convert_tuple(key, is_setter=True)
File "C:\Python\lib\site-packages\pandas\core\indexing.py", line 248, in _convert_tuple
idx = self._convert_to_indexer(k, axis=i, is_setter=is_setter)
File "C:\Python\lib\site-packages\pandas\core\indexing.py", line 1354, in _convert_to_indexer
return self._get_listlike_indexer(obj, axis, **kwargs)[1]
File "C:\Python\lib\site-packages\pandas\core\indexing.py", line 1161, in _get_listlike_indexer
raise_missing=raise_missing)
File "C:\Python\lib\site-packages\pandas\core\indexing.py", line 1246, in _validate_read_indexer
key=key, axis=self.obj._get_axis_name(axis)))
KeyError: "None of [Index(['H', 'I'], dtype='object')] are in the [columns]"
仅创建一列时,.loc方法效果很好。 (方括号也适用。)
>>> df.loc[:,'G'] = df['A']
>>> df
A B C D E F G
2000-01-01 -1.011264 -1.751948 0.059012 0.514253 -1.011264 -1.751948 -1.011264
2000-01-02 0.596959 0.348866 -1.011628 0.950259 0.596959 0.348866 0.596959
2000-01-03 0.305281 0.486400 -1.034534 -1.523402 0.305281 0.486400 0.305281
2000-01-04 -0.880457 0.379837 2.023866 1.588379 -0.880457 0.379837 -0.880457
2000-01-05 -1.142070 -0.168992 -0.391355 0.809820 -1.142070 -0.168992 -1.142070
2000-01-06 -0.335015 0.721563 -0.665120 -1.097811 -0.335015 0.721563 -0.335015
2000-01-07 -0.160611 -0.601393 -0.257349 -0.830527 -0.160611 -0.601393 -0.160611
2000-01-08 0.197624 -0.082786 1.335873 -0.841006 0.197624 -0.082786 0.197624
我对为什么.loc在创建多个列时不充当方括号感到困惑。我喜欢.loc []那样的显式方式,并且有时功能会受到限制,这让我很困扰。我想念什么吗?请问为什么在这种情况下它们的工作方式有所不同?
*原始问题的补充*
.loc []方法在分配给现有列时会生成NaN列。例如,
>>>df[['E','F']] = df[['A','B']]
>>> df
A B ... E F
2000-01-01 0.934380 -0.321112 ... 0.934380 -0.321112
2000-01-02 -0.760045 0.646212 ... -0.760045 0.646212
2000-01-03 0.645231 -0.910008 ... 0.645231 -0.910008
2000-01-04 -1.117132 2.595804 ... -1.117132 2.595804
2000-01-05 -1.273579 0.291202 ... -1.273579 0.291202
2000-01-06 0.142610 -0.368157 ... 0.142610 -0.368157
2000-01-07 0.567490 -1.598343 ... 0.567490 -1.598343
2000-01-08 1.300694 0.498405 ... 1.300694 0.498405
我生成了新的E,F列,并尝试使用.loc []方法从C,D分配新值。
>>>df.loc[:,['E','F']] = df[['C','D']]
>>>df
A B C D E F
2000-01-01 0.934380 -0.321112 0.747195 -0.991180 NaN NaN
2000-01-02 -0.760045 0.646212 -0.121421 2.262384 NaN NaN
2000-01-03 0.645231 -0.910008 0.170989 -1.552823 NaN NaN
2000-01-04 -1.117132 2.595804 0.569809 1.575253 NaN NaN
2000-01-05 -1.273579 0.291202 0.688443 -0.581674 NaN NaN
2000-01-06 0.142610 -0.368157 -0.674774 -1.961087 NaN NaN
2000-01-07 0.567490 -1.598343 -1.346179 -1.139205 NaN NaN
2000-01-08 1.300694 0.498405 -0.358015 -1.637471 NaN NaN
似乎使用.loc []仍然会引起问题。
答案 0 :(得分:1)
如前所述,它是有意完成的。以下是一些示例:
看起来与__getitem__
有关,[]
在使用df['H']
时被调用
让我们看看一些错误:
df.loc[:,'H']
向pandas\core\frame.py __getitem__
返回一个类似的错误,两者似乎都使用df['H'] = df['A']
df.loc[:, 'H'] = df['A']
,这就是为什么设置时它们表现相同的原因:
loc
当您将df.loc[:, ['H', 'I']]
与列表(df.loc[:, ['H']]
或pandas\core\frame.py __getitem__
)一起使用时,它不再使用pandas\core\indexing.py __getitem__
,而使用raise_missing
来设置{{1} }为_validate_read_indexer
此功能中有一个comment,它提供了一些信息:
# We (temporarily) allow for some missing keys with .loc, except in
# some cases (e.g. setting) in which "raise_missing" will be False
df[['H','I']]
使用pandas\core\frame.py __getitem__
,这就是设置时没有错误的原因。
这只是我对发生的事情的猜测。
关于df.loc[:,['E','F']] = df[['C','D']]
的其他问题在docs下的“交换列值的正确方法是使用原始值”中进行了说明。您应该使用to_numpy()
:df.loc[:,['E','F']] = df[['C','D']].to_numpy()
答案 1 :(得分:0)
这是在0.21.0之后放入熊猫的预期行为,请参见docs here。
错误消息的根源是此部分,数据框中缺少“ H”或“ I”:
df.loc[:,['H','I']]
使用带有.loc且缺少值的列表将引发KeyError。