【问题标题】:how to select/add a column to pandas dataframe based on a function of other columns?如何根据其他列的功能选择/添加一列到熊猫数据框?
【发布时间】:2015-03-10 18:48:12
【问题描述】:

我有一个数据框,我想选择符合某些条件的行。条件是其他列的值和一些附加值的函数。

这是一个玩具示例:

>>df = pd.DataFrame({'A': [1,2,3,4,5,6,7,8,9],
                   'B': [randint(1,9) for x in xrange(9)],
                   'C': [4,10,3,5,4,5,3,7,1]})
>>

      A  B   C
   0  1  6   4
   1  2  8  10
   2  3  8   3
   3  4  4   5
   4  5  2   4
   5  6  1   5
   6  7  1   3
   7  8  2   7
   8  9  8   1

我想选择某个函数返回 true 的所有行,例如如果乘法 AxC 在指定的列表 L 中,则 f(a,c,L) 返回 true,例如 L=[4,20,30](尽管该函数可能不那么简单)。也就是说,我想得到:

>>
      A  B   C
   0  1  6   4
   1  2  8  10
   3  4  4   5
   4  5  2   4
   5  6  1   5

同样,我想添加第四个二进制列“匹配”,即 True 是 L 中的 AxC:

      A  B   C  matched
   0  1  2   4    True
   1  2  5  10    True
   2  3  6   3   False
   3  4  3   5    True
   4  5  2   4    True
   5  6  6   5    True
   6  7  4   3   False
   7  8  5   7   False
   8  9  2   1   False

(添加此列后,您可以轻松选择所有带有 True 的行,但我怀疑一旦您可以添加,您也可以选择)。

是否有一种高效且优雅的方法可以在不显式迭代所有索引的情况下做到这一点? 谢谢!

【问题讨论】:

    标签: function select pandas add dataframe


    【解决方案1】:

    使用isin 的矢量化解决方案:

    In [5]:
    
    L=[4,20,30]
    df['Match'] = (df['A']*df['C']).isin(L)
    df
    Out[5]:
       A  B   C  Match
    0  1  6   4   True
    1  2  1  10   True
    2  3  8   3  False
    3  4  4   5   True
    4  5  2   4   True
    5  6  4   5   True
    6  7  4   3  False
    7  8  7   7  False
    8  9  4   1  False
    

    时间安排:

    In [9]:
    
    %%timeit
    L=[4,20,30]
    rowindex = df.apply(lambda x : True if (x['A'] * x['C']) in L else False, axis=1)
    df.loc[rowindex,'match'] = True
    df.loc[~rowindex,'match'] = False
    100 loops, best of 3: 3.13 ms per loop
    In [11]:
    
    %%timeit 
    L=[4,20,30]
    df['Match'] = (df['A']*df['C']).isin(L)
    
    1000 loops, best of 3: 678 µs per loop
    

    【讨论】:

    • 谢谢。这适用于一个简单的功能。我真正需要的(并且应该在问题中更清楚)是给定许多列表 L=[l1,l2,l3] 每对 df['A] 和 df['B'] 没有这两个同一个子列表中的值,这就是为什么我询问了一个以某种方式获取两个元素和列表的函数。
    • 你必须用你真正想要的来更新你的问题,否则这会浪费每个人试图击中移动目标的时间
    • 比我的好多了。不错,埃德
    • ehm,功能问题在问题中,但在示例中显然丢失了。这仍然是一个很好的问题,您提供了一个很好且有用的答案,所以我认为最好接受答案,关闭问题并发布一个新的、更清晰的问题。
    • @ScienceFriction 但这取决于您的功能,可以迭代(最坏情况)或使用矢量化方法(理想情况下)完成,w.r.t.到一个列表列表,您可以遍历每个子列表并使用isin 仍然测试成员身份
    【解决方案2】:

    这将返回一个布尔索引

    L=[4,20,30]
    df.apply(lambda x : True if (x['A'] * x['C']) in L else False, axis=1)
    
    0     True
    1     True
    2    False
    3     True
    4     True
    5     True
    6    False
    7    False
    8    False
    

    然后你可以做什么

    rowindex = df.apply(lambda x : True if (x['A'] * x['C']) in L else False, axis=1)
    df.loc[rowindex,'match'] = True
    df.loc[~rowindex,'match'] = False
    df
    
        A   B   C   match
    0   1   7   4   True
    1   2   3   10  True
    2   3   9   3   False
    3   4   5   5   True
    4   5   9   4   True
    5   6   2   5   True
    6   7   2   3   False
    7   8   7   7   False
    8   9   6   1   False
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 2017-01-14
      • 2021-06-25
      • 1970-01-01
      • 2020-10-21
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多