【问题标题】:Comparison of a Dataframe column values with a list数据框列值与列表的比较
【发布时间】:2017-05-27 15:04:49
【问题描述】:

考虑这个数据框:

df = pd.DataFrame({'A': [1, 1, 2, 2, 3, 3],
                   'B': [10, 15, 20, 25, 30,35],
                   'C': [100, 150, 200, 250, 300, 350]})

这是获取 C 列值的代码,它是每组的第一行(A 列):

firsts = df.groupby('A').first()['C']

所以首先是:(100, 200, 300)

现在我想添加新列,如果行的 C 列的值在 firsts 中,它将是 1,否则它将是 0

A B C D
1 10 100 1
1 15 150 0
2 20 200 1
2 25 250 0
3 30 300 1
3 35 350 0

我用过这个:

df['D'] = df['C'].apply(lambda x: 1 if x in firsts else 0)

但是输出是:

A B C D
1 10 100 0
1 15 150 0
2 20 200 0
2 25 250 0
3 30 300 0
3 35 350 0

如果有人解释为什么我的解决方案是错误的以及这个问题的实际解决方案是什么,我将不胜感激?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    你可以使用isin方法:

    df['D'] = df.C.isin(firsts).astype(int)
    
    df
    #   A   B   C   D
    #0  1   10  100 1
    #1  1   15  150 0
    #2  2   20  200 1
    #3  2   25  250 0
    #4  3   30  300 1
    #5  3   35  350 0
    

    您的方法失败的原因是 python in 运算符检查系列的索引而不是值,这与字典的工作方式相同:

    firsts
    #A
    #1    100
    #2    200
    #3    300
    #Name: C, dtype: int64
    
    1 in firsts
    # True
    
    100 in firsts
    # False
    
    2 in firsts
    # True
    
    200 in firsts
    # False
    

    如下修改您的方法:

    firstSet = set(firsts)
    df['C'].apply(lambda x: 1 if x in firstSet else 0)
    
    #0    1
    #1    0
    #2    1
    #3    0
    #4    1
    #5    0
    #Name: C, dtype: int64
    

    【讨论】:

      【解决方案2】:

      TL;DR:

      df['newColumn'] = np.where((df.compareColumn.isin(yourlist)), TrueValue, FalseValue)
      

      另一种一步法是使用np.where()isin

      import pandas as pd
      import numpy as np
      
      df = pd.DataFrame({'A': [1, 1, 2, 2, 3, 3],
                         'B': [10, 15, 20, 25, 30,35],
                         'C': [100, 150, 200, 250, 300, 350]})
      
      df['D'] = np.where((df.B.isin(firsts)), 1, 0)
      

      我们使用来自isin 的返回作为np.where() 中的条件来返回任一

      • 1True
      • 0False

      并将它们分配给同一数据框 df['D'] 中的新列。

      注意:np.where 允许使用 bitwise 运算符和替换案例来实现更复杂的条件,即在 False 上“绕过”

      df['col1'] = np.where(((df['col1'] == df['col2']) &
                             (~df['col1'].str.startswith('r'))),
                             'replace', df['col1'])
      

      【讨论】:

        【解决方案3】:

        您也可以使用.transform('first') 一步完成:

        In [280]: df['D'] = df.groupby('A')['C'].transform('first').eq(df['C']).astype(np.int8)
        
        In [281]: df
        Out[281]:
           A   B    C  D
        0  1  10  100  1
        1  1  15  150  0
        2  2  20  200  1
        3  2  25  250  0
        4  3  30  300  1
        5  3  35  350  0
        

        解释: GroupBy.transform('func') 向我们返回一个与应用func 的原始DF 长度相同的向量

        In [14]: df.groupby('A')['C'].transform('first')
        Out[14]:
        0    100
        1    100
        2    200
        3    200
        4    300
        5    300
        Name: C, dtype: int64
        
        In [15]: df.groupby('A')['C'].transform('max')
        Out[15]:
        0    150
        1    150
        2    250
        3    250
        4    350
        5    350
        Name: C, dtype: int64
        
        In [16]: df.groupby('A')['C'].transform('min')
        Out[16]:
        0    100
        1    100
        2    200
        3    200
        4    300
        5    300
        Name: C, dtype: int64
        
        In [17]: df.groupby('A')['C'].transform('mean')
        Out[17]:
        0    125
        1    125
        2    225
        3    225
        4    325
        5    325
        Name: C, dtype: int64
        
        In [18]: df.groupby('A')['C'].transform('sum')
        Out[18]:
        0    250
        1    250
        2    450
        3    450
        4    650
        5    650
        Name: C, dtype: int64
        

        【讨论】:

        • 请您解释一下'transform('first')' 在这里做什么? (我找不到转换的简单解释)
        • @MehrdadSComputer,我已经添加了解释 - 我希望现在更清楚
        • 谢谢。所以它有点像“应用”功能。
        【解决方案4】:

        firsts 是 pandas 系列,所以当我们使用 in 搜索值时,它会在索引列表中搜索该值来解决这个问题,我们可以将 firsts 转换为列表或数组

        %timeit df['D'] = df['C'].apply(lambda x: 1 if x in firsts.values else 0)
        

        每个循环 314 µs ± 17.3 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)

        %timeit df['D'] = df['C'].apply(lambda x: 1 if x in list(firsts) else 0)
        

        每个循环 301 µs ± 11.2 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)

        %timeit df['D'] = list(map(lambda x: 1 if x in list(firsts) else 0,list(df['C'])))
        

        每个循环 27.6 µs ± 1.02 µs(7 次运行的平均值 ± 标准偏差,每次 10000 个循环)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-18
          • 1970-01-01
          相关资源
          最近更新 更多