【问题标题】:Assign a tuple to multiple elements of a pandas dataframe将元组分配给熊猫数据框的多个元素
【发布时间】:2016-06-23 15:32:55
【问题描述】:

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

>>> 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)

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

实际输出:

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 的回答。

【问题讨论】:

    标签: python pandas indexing


    【解决方案1】:

    您必须构造一个 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))]
    

    并将其作为数据 arg 传递给 Series 以生成:

    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 上进行屏蔽时,它只需要满足条件的行

    【讨论】:

    • 感谢@EdChum,但它仍然没有达到我想要的效果。不确定它在这里试图做什么,看看我上面的编辑。
    • 但是,如果您查看生成的系列,您并没有做同样的事情,索引从 0 变为 2,因此只有第 2 行被分配,我正在生成一个与非蒙面系列匹配的系列所以它正确对齐
    • 哦,对不起,我误解了你的意思。我没有意识到在赋值中使用了行索引,我认为它更像 numpy 并逐个元素地分配元素。当然,现在我想起来这也是有道理的。感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2021-09-06
    相关资源
    最近更新 更多