代码之家  ›  专栏  ›  技术社区  ›  Xavier

根据条件从数据帧中选择行

  •  1
  • Xavier  · 技术社区  · 8 年前

    我有一个数据帧:

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

    i、 例如,对于第一列中的相同ID,它检查Val列,赋予“high”值高于“Low”或“Mod”,然后从Val列中具有“high”的ID行中选择“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

    1 回复  |  直到 8 年前
        1
  •  0
  •   juanpa.arrivillaga    8 年前

    编辑以添加

    真的 潘多尼克 这样做的方法是 类别 :

    >>> 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”更高的优先级,然后从该ID在Val列中具有“high”的行中,选择在“Num”列中具有更高值的行。”=&燃气轮机;按Val排序,然后按Num(降序)排序,然后取最高值。