【问题标题】:Selecting rows based on a column value根据列值选择行
【发布时间】:2018-01-20 10:08:37
【问题描述】:

我有一个类似这样的数据框

data = {'ID': [1,2,3,4,5,6,7,8,9],
       'Doc':['Order','Order','Inv','Order','Order','Shp','Order', 'Order','Inv'],
       'Rep':[101,101,101,102,102,102,103,103,103]}
frame = pd.DataFrame(data)


    Doc     ID  Rep
0   Order   1   101
1   Order   2   101
2   Inv     3   101
3   Order   4   102
4   Order   5   102
5   Shp     6   102
6   Order   7   103
7   Order   8   103
8   Inv     9   103

现在我想为 Rep 选择 Doc 类型仅为 Inv 的行。

我想要一个数据框

    Doc     ID  Rep
0   Order   1   101
1   Order   2   101
2   Inv     3   101
6   Order   7   103
7   Order   8   103
8   Inv     9   103

所有代表都会有 Doc 类型的 Orders,所以我试图做这样的事情

frame[frame.Rep == frame.Rep[frame.Doc == 'Inv']] 

但我得到一个错误

ValueError: 只能比较标签相同的 Series 对象

【问题讨论】:

    标签: pandas slice


    【解决方案1】:

    您可以使用两次boolean indexing - 首先按条件获取所有Rep,然后按isin 获取所有行:

    a = frame.loc[frame['Doc'] == 'Inv', 'Rep']
    print (a)
    2    101
    8    103
    Name: Rep, dtype: int64
    
    df = frame[frame['Rep'].isin(a)]
    print (df)
         Doc  ID  Rep
    0  Order   1  101
    1  Order   2  101
    2    Inv   3  101
    6  Order   7  103
    7  Order   8  103
    8    Inv   9  103
    

    query 的解决方案:

    a = frame.query("Doc == 'Inv'")['Rep']
    df = frame.query("Rep in @a")
    print (df)
         Doc  ID  Rep
    0  Order   1  101
    1  Order   2  101
    2    Inv   3  101
    6  Order   7  103
    7  Order   8  103
    8    Inv   9  103
    

    时间安排

    np.random.seed(123)
    N = 1000000
    L = ['Order','Shp','Inv']
    frame = pd.DataFrame({'Doc': np.random.choice(L, N,  p=[0.49, 0.5, 0.01]),
                         'ID':np.arange(1,N+1),
                         'Rep':np.random.randint(1000, size=N)})
    print (frame.head())
    
         Doc  ID  Rep
    0    Shp   1   95
    1  Order   2  147
    2  Order   3  282
    3    Shp   4   82
    4    Shp   5  746
    
    In [204]: %timeit (frame.groupby('Rep').filter(lambda x: 'Inv' in x['Doc'].values))
    1 loop, best of 3: 250 ms per loop
    
    In [205]: %timeit (frame[frame['Rep'].isin(frame.loc[frame['Doc'] == 'Inv', 'Rep'])])
    100 loops, best of 3: 17.3 ms per loop
    
    In [206]: %%timeit
         ...: a = frame.query("Doc == 'Inv'")['Rep']
         ...: frame.query("Rep in @a")
         ...: 
    100 loops, best of 3: 14.5 ms per loop
    

    编辑:

    感谢John Galt 的好建议:

    df = frame.query("Rep in %s" % frame.query("Doc == 'Inv'")['Rep'].tolist()) 
    print (df)
         Doc  ID  Rep
    0  Order   1  101
    1  Order   2  101
    2    Inv   3  101
    6  Order   7  103
    7  Order   8  103
    8    Inv   9  103
    

    【讨论】:

    • 这可能不可读,但可以用frame.query("Rep in %s" % frame.query("Doc == 'Inv'")['Rep'].tolist())单数
    【解决方案2】:
    import pandas as pd
    
    
    frame_Filtered=frame[frame['Doc'].str.contains('Inv|Order')]
    
    print(frame_Filtered)
    

    我得到的输出

         Doc  ID  Rep
         0  Order   1  101
         1  Order   2  101
         2    Inv   3  101
         3  Order   4  102
         4  Order   5  102
         6  Order   7  103
         7  Order   8  103
         8    Inv   9  103
    

    【讨论】:

    • 谢谢,但我不想要 Rep 102。我只想要只有 Inv 和 Order 的 Rep。
    猜你喜欢
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多