Панды: проверьте, является ли хотя бы одно из значений в строках дубликатов 1 - PullRequest
0 голосов
/ 15 ноября 2018

Эта проблема может быть довольно специфической, но я уверен, что многие могут столкнуться с этим. Таким образом, у меня есть DataFrame в форме как:

asd = pd.DataFrame({'Col1': ['a', 'b', 'b','a','a'], 'Col2': [0,0,0,1,1]})

Полученная таблица выглядит следующим образом:

I -- Col1 -- Col2
1 -- a    -- 0
2 -- b    -- 0
3 -- b    -- 0
4 -- a    -- 1
5 -- a    -- 1

Что я пытаюсь сделать, это:
если хотя бы одно значение "a" в Col1 имеет соответствующее значение 1 в Col2, то в Col3 мы ставим 1 для всех значений "a"
в противном случае (если хотя бы один «а» не имеет значения 1), мы помещаем «0» для всех значений «а»
И затем повторите для всех других значений в Col1.

Результат операции должен выглядеть следующим образом:

I -- Col1 -- Col2 -- Col3
1 -- a    -- 0    -- 1     because "a" has value of 1 in 4th and 5th lines
2 -- b    -- 0    -- 0     because all "b" have values of 0
3 -- b    -- 0    -- 0
4 -- a    -- 1    -- 1
5 -- a    -- 1    -- 1

В настоящее время я делаю это:

asd['Col3'] = 0
col1_uniques = asd.drop_duplicates(subset='Col1')['Col1']
small_dataframes = []

for i in col1_uniques:
    small_df = asd.loc[asd.Col1 == i]
    if small_df.Col2.max() == 1:
        small_df['Col3'] = 1

    small_dataframes.append(small_df)

Затем я снова собираю фрейм данных.

Однако это занимает слишком много времени (у меня около 80000 уникальных значений в Col1). На самом деле, пока я писал это, он не закончил даже четверть этой работы.

Есть ли лучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Насколько я понимаю, вам нужно повторить процесс для всех уникальных значений в Col1, вам потребуется groupby,

asd['Col3'] = asd.groupby('Col1').Col2.transform(lambda x: x.eq(1).any().astype(int))

    Col1    Col2    Col3
0   a       0       1
1   b       0       0
2   b       0       0
3   a       1       1
4   a       1       1

Вариант 2: Решение, аналогичное описанному выше, но с использованием карты

d = asd.groupby('Col1').Col2.apply(lambda x: x.eq(1).any().astype(int)).to_dict()
asd['Col3'] = asd['Col1'].map(d)
0 голосов
/ 15 ноября 2018

Другой метод без groupby и более быстрый, используя np.where и isin:

v = asd.loc[asd['Col2'].eq(1), 'Col1'].unique()
asd['Col3'] = np.where(asd['Col1'].isin(v), 1, 0)

print(asd)
  Col1  Col2  Col3
0    a     0     1
1    b     0     0
2    b     0     0
3    a     1     1
4    a     1     1
0 голосов
/ 15 ноября 2018

Вы можете сделать это с помощью groupby и оператора if. Первая группа всех предметов по Col1:

lists = asd.groupby("Col1").agg(lambda x: tuple(x))

Это дает вам:

           Col2
Col1           
a     (0, 1, 1)
b        (0, 0)

Затем вы можете выполнять итерацию по уникальным значениям индекса в списках, маскируя исходный DataFrame и устанавливая для Col3 значение 1, если в списках обнаружена 1 [* Col2 ”].

asd["Col3"] = 0
for i in lists.index:
    if 1 in lists.loc[i, "Col2"]:
        asd.loc[asd["Col1"]==i, "Col3"] = 1

В результате:

    Col1    Col2    Col3
0   a   0   1
1   b   0   0
2   b   0   0
3   a   1   1
4   a   1   1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...