【问题标题】:Selecting rows from a dataframe based on conditions根据条件从数据框中选择行
【发布时间】:2018-03-02 03:20:31
【问题描述】:

我有一个数据框:

>>> d = {'ID' : ['ABC', 'ABC', 'ABC', 'DFG', 'DFG', 'DFG', 'EGF', '2BD', '2BD'], 'Val': ['High', 'Low', 'High', 'High', 'High', 'Low', 'Low', 'Low', 'High'], 
... 'Num': [22,2,16,10,50,3,2,34,2], 'Val2':['Low', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High']}
>>> import pandas as pd
>>> df = pd.DataFrame(d)
>>> df
    ID  Num   Val  Val2
0  ABC   22  High   Low
1  ABC    2   Low  High
2  ABC   16  High   Low
3  DFG   10  High  High
4  DFG   50  High  High
5  DFG    3   Low  High
6  EGF    2   Low  High
7  2BD   34   Low  High
8  2BD    2  High  High

有没有办法对列中具有相同值的行应用条件,然后应用一些条件来检查其他列中的值?

我想要这样的输出:

ID | Val | Num | Val2

ABC | High | 22 | Low
DFG | High | 50 | High
EGF | Low  | 2  | High
2BD | High  | 2  | High

即,对于第一列中的相同 ID,它检查 Val 列,将“High”值优先于“Low”或“Mod”,然后从具有“High”的 ID 的行中在 Val 列中选择“Num”列中具有较高值的​​行。

我是这样做的:

import pandas as pd
d = {'ID' : ['ABC', 'ABC', 'ABC', 'DFG', 'DFG', 'DFG', 'EGF', '2BD', '2BD'], 'Val': ['High', 'Low', 'High', 'High', 'High', 'Low', 'Low', 'Low', 'High'], 'Num': [22,2,16,10,50,3,2,34,2], 'Val2':['Low', 'High', 'Low', 'High', 'High', 'High', 'High', 'High', 'High']}
df = pd.DataFrame(d)
print df

x = df.ID.unique().tolist()
f_df=pd.DataFrame()
idlist=[]
vallist=[]
numlist=[]

for i in x:
    idlist.append(i)
    new_df = df.loc[df['ID'] == i]
    h_df = new_df.loc[df['Val'] == 'High']
    if h_df.empty:
        m_df = new_df.loc[df['Val'] == 'Mod']
        if m_df.empty:
            l_df = new_df.loc[df['Val'] == 'Low']
            vallist.append('Low')
            if len(l_df) > 1:
                m = l_df['Num'].max()
                numlist.append(m)
            else:
                m = l_df['Num'].max()
                numlist.append(m)
        else:
            vallist.append('Mod')
            if len(m_df) > 1:
                m = m_df['Num'].max()
                numlist.append(m)
            else:
                m = m_df['Num'].max()
                numlist.append(m)

    else:
        vallist.append('High')
        if len(h_df) > 1:
            m = h_df['Num'].max()
            numlist.append(m)
        else:
            m = h_df['Num'].max()
            numlist.append(m)

f_df['ID'] = idlist
f_df['Val'] = vallist
f_df['Num'] = numlist

print f_df

有没有更好的方法来做到这一点?另外,如何在输出中获得Val2的对应值?因为我实际上有一个包含 12 列的数据框。

【问题讨论】:

    标签: python pandas dataframe conditional


    【解决方案1】:

    编辑添加

    真正的 pandonic 方法是使用 categories

    >>> df['Val'] = df.Val.astype('category').cat.set_categories(['High','Mod','Low'], ordered=True)
    >>> df['Val2'] = df.Val2.astype('category').cat.set_categories(['High','Mod','Low'], ordered=True)
    >>> df
        ID  Num   Val  Val2
    0  ABC   22  High   Low
    1  ABC    2   Low  High
    2  ABC   16  High   Low
    3  DFG   10  High  High
    4  DFG   50  High  High
    5  DFG    3   Low  High
    6  EGF    2   Low  High
    7  2BD   34   Low  High
    8  2BD    2  High  High
    >>> df.dtypes
    ID        object
    Num        int64
    Val     category
    Val2    category
    dtype: object
    

    所以现在排序可以按照我们的意愿进行!

    >>> (df.sort_values(['Val','Num'], ascending=[True, False])
    ...    .groupby('ID')
    ...    .nth(0))
         Num   Val  Val2
    ID
    2BD    2  High  High
    ABC   22  High   Low
    DFG   50  High  High
    EGF    2   Low  High
    

    原始答案

    是的,我认为你不想使用内置排序和groupby,所以首先,创建将“High”、“Mod”和“Low”值映射到数字的列 这样我们就可以轻松地与他们合作:

    >>> df['valmap'] = df.Val.map({'High':0, 'Mod':1, 'Low':2})
    >>> df['val2map'] = df.Val2.map({'High':0, 'Mod':1, 'Low':2})
    >>> df
        ID  Num   Val  Val2  valmap  val2map
    0  ABC   22  High   Low       0        2
    1  ABC    2   Low  High       2        0
    2  ABC   16  High   Low       0        2
    3  DFG   10  High  High       0        0
    4  DFG   50  High  High       0        0
    5  DFG    3   Low  High       2        0
    6  EGF    2   Low  High       2        0
    7  2BD   34   Low  High       2        0
    8  2BD    2  High  High       0        0
    

    然后我想你只是想要:

    >>> df.sort_values(['valmap','Num'], ascending=[True, False]).groupby('ID').nth(0)
         Num   Val  Val2  val2map  valmap
    ID
    2BD    2  High  High        0       0
    ABC   22  High   Low        2       0
    DFG   50  High  High        0       0
    EGF    2   Low  High        0       2
    

    当然,您可以始终选择您想要的列:

    >>> (df.sort_values(['valmap','Num'], ascending=[True, False])
    ...    .groupby('ID')['Num','Val', 'Val2']
    ...    .nth(0))
    
         Num   Val  Val2
    ID
    2BD    2  High  High
    ABC   22  High   Low
    DFG   50  High  High
    EGF    2   Low  High
    

    所以,如果您考虑一下您的要求:

    "对于第一列中的相同 ID," => 使用 groupby('ID')

    “将'High'值优先于'Low'或'Mod',然后从Val列中具有'High'的ID的行中选择'Num'列中具有更高值的行。 " => 按 Val 排序,然后按 Num(降序),然后取最高值。

    【讨论】:

    • 哇!完美的!这就是我一直在寻找的。谢谢。
    • @Xavier 我编辑使用类别,这是 pandas 的一个非常方便的功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    相关资源
    最近更新 更多