Как написать функцию pandas или dask, чтобы получить следующий результат? - PullRequest
1 голос
/ 18 июня 2020

Я хочу создать столбец «Условие» на основе следующих условий:

  • Если есть A и B для «Уникальной группы», то условие истинно для всей группы
  • Может быть один A и несколько B или наоборот, и условие все равно будет True.
  • Если есть A, а B нет, или наоборот, условие для всей «Уникальной группы» is False
+----+--------------+------+-----------+
| ID | Unique Group | Name | CONDITION |
+----+--------------+------+-----------+
|  0 |         4133 | D    | True      |
|  1 |         4133 | A    | True      |
|  2 |         4133 | B    | True      |
|  3 |         4133 | C    | True      |
|  4 |         3187 | A    | False     |
|  5 |         3187 | A    | False     |
|  6 |         3187 | C    | False     |
|  7 |         5788 | A    | True      |
|  8 |         5788 | B    | True      |
+----+--------------+------+-----------+

У меня есть приблизительное представление, что как только я получу уникальную группу и соответствующее условие, я могу выполнить слияние, чтобы получить 'Condition' для всех тех же идентификаторов группы, но я Я не знаю, как получить условие для отдельного идентификатора группы.

Ответы [ 3 ]

1 голос
/ 18 июня 2020

Нет необходимости создавать какой-либо простой набор pythoni c, так как Pandas имеет свои собственные методы для работы с такими случаями.

Там Также нет необходимости «умножать» ответ. Благодаря функции широковещательной передачи , Pandas делает это самостоятельно, поэтому функция, переданная в transform , может возвращать single значение.

Итак, гораздо более простое решение, чем другой ответ:

df['condition'] = df.groupby('Unique Group').Name.transform(
    lambda grp: grp.str.contains('A').any() and grp.str.contains('B').any())

С другой стороны, другое решение работает быстрее моего. На ваш выбор, какой из них применить в вашем случае.

1 голос
/ 18 июня 2020

Для pandas И dask попробуйте ...

df1 = df.groupby('Unique Group')['Name'].apply(list).reset_index()
df2 = df.merge(df1, how='left', on='Unique Group',  suffixes=('', '_y'))
df2['Temp'] = True
df2['CONDITION'] = df2['Temp'][df2['Name_y'].apply(lambda x: 'A' in x and 'B' in x)]
df2['CONDITION'] = df2['CONDITION'].fillna(False)
df2 = df2.drop(['Temp', 'Name_y'], axis=1)

Насколько мне известно, вы не можете использовать .transform и np.where() с Dask ... отсюда и дополнительные код ...

Всего за pandas ... попробуйте с .tranform, .join, str.split и, наконец, np.where

df['CONDITION'] = df.groupby('Unique Group')['Name'].transform(lambda x: ','.join(x)).str.split(',')
df['CONDITION'] = np.where((df['CONDITION'].apply(lambda x: 'A' in x and 'B' in x)), True, False)

ОБНОВЛЕНИЕ: Чтобы задать ответ на комментарий ... не уверен, что происходит со ВСЕМИ вашими данными, но из предоставленных образцов данных это сработало, но я получил предупреждающее сообщение ... чтобы быть в безопасности, вы должны указать типы данных для столбцов с meta=('ID':'int64','Unique Group':'int64', 'Name':'object','Condition':'bool') или любые другие типы данных.

enter image description here

0 голосов
/ 18 июня 2020

Вот решение, использующее преобразование:

def check_a_b(ser):
    s = set(ser)
    if "A" in s and "B" in s:
        return [True] * len(ser)
    else:
        return [False] * len(ser)

df["condition"] = df.groupby("Unique Group")["Name"].transform(check_a_b)

Результат:

   ID  Unique Group Name  condition
0   0          4133    D       True
1   1          4133    A       True
2   2          4133    B       True
3   3          4133    C       True
4   4          3187    A      False
5   5          3187    A      False
6   6          3187    C      False
7   7          5788    A       True
8   8          5788    B       True
...