Создание нового столбца и присвоение значений, если какая-либо строка в группе содержит определенное значение - PullRequest
2 голосов
/ 02 мая 2019

Я пытаюсь присвоить значения новому столбцу для каждой группы в группе на основе: если какая-либо из строк в группе содержит определенное значение, то значения новых столбцов для этой группы должны быть определенным значением.

До сих пор я пытался использовать np.where и pandas dataframe any () и применить его для группировки по. Это сработало для очень маленького набора данных. Мой исходный набор данных содержит около 1,8 миллиона записей, и метод, который я пробовал, слишком медленный, он никогда не завершается в исходном наборе данных. Так что интересно, если есть эффективный способ достичь этого.

Например, если у меня есть кадр данных со столбцами 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 есть бета, столбец «D» (все строки D) для этой группы должен быть бета. Если ни одна из строк в группе не содержит бета, следующая иерархия имеет косинус, то есть, если какая-либо строка столбца 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

Ответы [ 2 ]

4 голосов
/ 02 мая 2019

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 голос
/ 02 мая 2019

Numpy

Мне пришло в голову использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...