我想将一个元组分配给数据框的布尔索引切片,如下所示:

>>> import pandas as pd
>>> mydataframe = pd.DataFrame([1,2,3,4,5],columns=['colname'])
>>> mydataframe.loc[mydataframe['colname']>2,'colname'] = (1,2)


所需的输出:

>>> mydataframe
   colname
0        1
1        2
2        (1,2,3)
3        (1,2,3)
4        (1,2,3)


但是,熊猫没有将元组的每个元素分配给切片,而是尝试将元组的每个元素分配给切片中的元素,并且由于形状不匹配而出错。

实际输出:

ValueError: shape mismatch: value array of shape (2,) could not be broadcast
to indexing result of shape (3,)


我试过使用set_value函数,并得到相同的行为:

>>> mydataframe.set_value(mydataframe['colname']>2,'colname', (1,2))
ValueError: shape mismatch: value array of shape (2,) could not be broadcast
to indexing result of shape (3,)


该问题适用于分配给数据框中的单个元素:Add a tuple to a specific cell of a pandas dataframe

有没有一种方法可以执行此分配而无需遍历切片中的元素?

编辑:
我还按照EdChum的答案尝试了以下操作,但仍未达到预期的效果:

>>> mydataframe = pd.DataFrame([1,2,3,4,5],columns=['colname'])
>>> assignment_series = pd.Series([(1,2,3)]*np.sum(mydataframe['colname']>2))
    >>>> assignment_series
0    (1, 2, 3)
1    (1, 2, 3)
2    (1, 2, 3)
dtype: object
>>> mydataframe.loc[mydataframe['colname']>2,'colname'] = assignment_series
>>> mydataframe
     colname
0          1
1          2
2  (1, 2, 3)
3        NaN
4        NaN


编辑2:
抱歉,我误解了EdChum的回答。之前的编辑不是他在说什么,assignment_series的长度应与mydataframe相同,而不是像我上面所做的mydataframe.loc [mydataframe ['colname']> 2,'colname']相同。请参阅下面的EdChum的答案。

最佳答案

您必须构造一个Series,其中元组重复df的长度,以便对齐:

In [37]:
mydataframe = pd.DataFrame([1,2,3,4,5],columns=['colname'])
mydataframe.loc[mydataframe['colname']>2,'colname']=pd.Series([(1,2,3) for x in range(len(mydataframe))])
mydataframe

Out[37]:
     colname
0          1
1          2
2  (1, 2, 3)
3  (1, 2, 3)
4  (1, 2, 3)


因此,这里的关键点是您想为每行分配一个元组作为单个元素,因此您需要匹配所需的形状,这是一个5行系列,其索引与lhs相匹配,我们使用列表推导重复元组N行时间:

[(1,2,3) for x in range(len(mydataframe))]


并将其作为Series产生的数据arg传递:

In [39]:
pd.Series([(1,2,3) for x in range(len(mydataframe))])

Out[39]:
0    (1, 2, 3)
1    (1, 2, 3)
2    (1, 2, 3)
3    (1, 2, 3)
4    (1, 2, 3)
dtype: object


当您在lhs上屏蔽时,它仅占用满足条件的行

10-06 13:32