【问题标题】:Creating a new column and assigning values if any one of the row within a group contains a certain value如果组中的任何一行包含某个值,则创建一个新列并分配值
【发布时间】:2019-05-02 17:42:01
【问题描述】:

我正在尝试根据以下条件为 group by 中的每个组分配值:如果组中的任何一行包含特定值,则该组的新列值应该是某个值。

到目前为止,我已经尝试使用 np.where 和 pandas 数据框 any() 并将其应用于分组依据。这适用于非常小的数据集。我的原始数据集包含大约 180 万条记录,我尝试过的方法太慢,它永远不会在原始数据集上运行完成。所以想知道是否有有效的方法来实现这一点。

例如,如果我有一个包含 A、B 和 C 列的数据框

     A      B   C
0   alpha   m   t
1   beta    n   r
2   cosine  q   f
3   alpha   m   t
4   beta    m   t
5   alpha   n   r
6   cosine  q   f

对于 B 和 C 组,创建一个新列“D”,其值基于“A”。在一个组中,如果 A 列的任何一行具有 beta,则该组的“D”列(D 的所有行)应该是 beta。如果组中没有任何行包含 beta,则下一个层次结构是余弦,即,如果该组中 A 列的任何行具有余弦,则该组中 D 列的所有行都应该是余弦。

目前为止我尝试过的方法:

def test(dft):
    dft['D']=np.where(dft[dft['A']=='beta'].any(),'beta',np.where(dft[dft['A']=='cosine'].any(),'cosine',np.where(dft[dft['A']=='alpha'].any(),'alpha',dft['A'])))
    return dft['D']
dft2=dft.groupby(['B','C']).apply(test)
dft2=dft2.reset_index()

我得到的结果是:

    B   C   level_2    D
0   m   t   0         beta
1   m   t   3         beta
2   m   t   4         beta
3   n   r   1         beta
4   n   r   5         beta
5   q   f   2         cosine
6   q   f   6         cosine

预期结果应如下所示:

     A      B   C          D
0   alpha   m   t        beta
1   beta    n   r        beta
2   cosine  q   f        cosine
3   alpha   m   t        beta
4   beta    m   t        beta
5   alpha   n   r        beta
6   cosine  q   f        cosine

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    IIUC 使用 Categorical 转换您的列 A ,然后执行 groupby transform

    df.A=pd.Categorical(df.A,categories=['alpha','cosine','beta'],ordered=True)
    df.groupby(['B','C']).A.transform('max')
    Out[1200]: 
    0      beta
    1      beta
    2    cosine
    3      beta
    4      beta
    5      beta
    6    cosine
    Name: A, dtype: object
    df['D']=df.groupby(['B','C']).A.transform('max')
    

    【讨论】:

    • 非常聪明 (-:
    • 非常聪明 确实!非常感谢! @文本
    【解决方案2】:

    麻木

    我想到了使用 Numpy。这主要是为了我的利益,但如果其他人感兴趣,我想我会分享。

    # This will assign a factorized version of the combination of `df.B` and `df.C`
    # `i` will be the integer factor values
    # `u` will have the unique tuples that are the combinations themselves
    i, u = pd.factorize([*zip(df.B, df.C)])
    
    # `order` acts as both the labels and the priority ordering
    order = np.array(['beta', 'cosine', 'alpha'])
    # use Numpy broadcasting to see get a boolean version of one-hot encoded values
    conds = df.A.values == order[:, None]
    
    # create a new array that has the same number of rows as the number of unique
    # combinations of `'B'` and `'C'`... or `len(u)` and the number of columns equal
    # to the number of items in `order`
    out = np.zeros((len(u), len(order)), bool)
    
    j = np.tile(i, len(u))
    k = np.arange(len(u)).repeat(len(i))
    
    # Surgically place cumulative or evaluations into the `out` array
    np.logical_or.at(out, (k, j), conds.ravel())
    
    df.assign(D=np.select(out, order)[i])
    
            A  B  C       D
    0   alpha  m  t    beta
    1    beta  n  r    beta
    2  cosine  q  f  cosine
    3   alpha  m  t    beta
    4    beta  m  t    beta
    5   alpha  n  r    beta
    6  cosine  q  f  cosine
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 2022-08-13
      • 1970-01-01
      • 1970-01-01
      • 2022-07-05
      相关资源
      最近更新 更多