Панды проверяет, нет лиистина в каждой группе равна 1 - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть следующие df,

cluster_id    dummy
1             False
1             True
1             True
2             False
2             False
3             False
3             True

Я хочу создать логический столбец 'dummy_display', для которого установлено значение False, если в каждом кластере есть хотя бы один dummy == True и число значений True меньше длины кластера, поэтому результаты должны выглядеть примерно так:

cluster_id    dummy     dummy_display
1             False     False
1             True      False
1             True      False
2             False     True
2             False     True
3             False     False
3             True      False

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

По моему мнению ...

@ Ответ Ноля более прост и должен быть подходом goto.Но я не мог не предоставить альтернативу Numpy.

i, u = pd.factorize(df.cluster_id)
a = np.zeros(len(u), np.bool8)
np.logical_or.at(a, i, df.dummy.values)

df.assign(dummpy_display=a[i])

   cluster_id  dummy  dummpy_display
0           1  False            True
1           1   True            True
2           1   True            True
3           2  False           False
4           2  False           False
5           3  False            True
6           3   True            True

Разбивка

pandas.factorize создает массив целых чисел, представляющих уникальные значения в df.cluster_id

i, u = pd.factorize(df.cluster_id)
print(f"factorization (i): {[*i]}\nunique values (u): {[*u]}")

factorization (i): [0, 0, 0, 1, 1, 2, 2]
unique values (u): [1, 2, 3]

Затем мы инициализируем False значения для каждого уникального cluster_id

a = np.zeros(len(u), np.bool8)
print(f"accumulated `or` init (a): {[*a]}")

accumulated `or` init (a): [False, False, False]

Затем используем функцию np.logical_or.at для накопления с использованием логики or с учетом заданных индексов и логических значений

np.logical_or.at(a, i, df.dummy.values)
print(f"accumulated `or` post (a): {[*a]}")
print(f"broadcast over factorization (a[i]):\n  {[*a[i]]}")

accumulated `or` post (a): [True, False, True]
broadcast over factorization (a[i]):
  [True, True, True, False, False, True, True]

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

a = [False, False, False]
print(f"accumulate `or` init (a): {a}", end='\n\n')

d = df.assign(i=i, a=None)[['cluster_id', 'i', 'dummy', 'a']]

for j in d.index:
  a[d.at[j, 'i']] |= d.at[j, 'dummy']
  d.at[j, 'a'] = [*a]

d


   cluster_id  i  dummy                              a
            at ↓     ⇩  or a[0]          ⇩
0           1  0  False              [False, False, False]
                             ╭──────────⤴
            at ↓     ⇩  or a[0] ==       ⇩
1           1  0   True               [True, False, False]
                             ╭──────────⤴
            at ↓     ⇩  or a[0] ==       ⇩
2           1  0   True               [True, False, False]
                             ╭─────────────────⤴
            at ↓     ⇩  or a[1] ==              ⇩
3           2  1  False               [True, False, False]
                             ╭─────────────────⤴
            at ↓     ⇩  or a[1] ==              ⇩
4           2  1  False               [True, False, False]
                             ╭────────────────────────⤴
            at ↓     ⇩  or a[2] ==                     ⇩
5           3  2  False               [True, False, False]
                             ╭────────────────────────⤴
            at ↓     ⇩  or a[2] ==                     ⇩
6           3  2   True                [True, False, True]

И то же вещание, которое мы показали выше

print(f"result (a): {a}\nbroadcasted (a[i]):\n  {[a[j] for j in i]}")

result (a): [True, False, True]
broadcasted (a[i]):
  [True, True, True, False, False, True, True]
0 голосов
/ 11 сентября 2018

Используйте transform с any

In [137]: ~df.groupby('cluster_id')['dummy'].transform('any')
Out[137]:
0    False
1    False
2    False
3     True
4     True
5    False
6    False
Name: dummy, dtype: bool

In [139]: df['dummy_display'] = ~df.groupby('cluster_id')['dummy'].transform('any')

In [140]: df
Out[140]:
   cluster_id  dummy  dummy_display
0           1  False          False
1           1   True          False
2           1   True          False
3           2  False           True
4           2  False           True
5           3  False          False
6           3   True          False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...