我正尝试根据以下方式为组中每个组的新列分配值:如果组中的任何行包含特定值,则该组的新列值应为某个值。
到目前为止,我已经尝试使用np.where和pandas dataframe 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
答案 0 :(得分:4)
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')
答案 1 :(得分:1)
我想使用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