Есть ли способ l oop через фрейм данных python, сравнить значение столбца (вложенный список) и условно обновить другой столбец? - PullRequest
1 голос
/ 02 марта 2020

У меня есть python фрейм данных, как показано ниже:

A   B      C
2  [4,3,9] 1
6  [4,8]   2
3  [3,9,4] 3

Моя цель - провести l oop через фрейм данных и сравнить столбец B, если столбец B совпадает, столбец обновления C по тому же номеру, как показано ниже:

A   B      C
2  [4,3,9] 1
6  [4,8]   2
3  [3,9,4] 1

Я попытался с кодом ниже:

for i, j in df.iterrows():
  if len(df['B'][i]  ==len(df['B'][j] & collections.Counter(df['B'][i]==collections.Counter(df['B'][j])
     df['C'][j]==df['C'][i]
  else:
     df['C'][j]==df['C'][j]

Я получил сообщение об ошибке типа unhashable: 'list'

Кто-нибудь знает, что является причиной этой ошибки и лучший способ сделать это? Спасибо за вашу помощь!

Ответы [ 3 ]

0 голосов
/ 02 марта 2020

Создайте временный столбец, применяя sorted к каждой записи в столбце B; группируйте по временному столбцу, чтобы получить совпадения и избавиться от временного столбца.

df1['B_temp'] = df1.B.apply(lambda x: ''.join(sorted(x)))

df1['C'] = df1.groupby('B_temp').C.transform('min')

df1 = df1.drop('B_temp', axis = 1)

df1

    A      B        C
0   2   [4, 3, 9]   1
1   6   [4, 8]      2
2   3   [3, 9, 4]   1
0 голосов
/ 02 марта 2020

Поскольку списки не могут быть хэшируемыми, преобразуйте списки в отсортированные кортежи и получите первые значения по GroupBy.transform с GroupBy.first:

df['C'] = df.groupby(df.B.apply(lambda x: tuple(sorted(x)))).C.transform('first')
print (df)
   A          B  C
0  2  [4, 3, 9]  1
1  6     [4, 8]  2
2  3  [3, 9, 4]  1

Деталь :

print (df.B.apply(lambda x: tuple(sorted(x))))
0    (3, 4, 9)
1       (4, 8)
2    (3, 4, 9)
Name: B, dtype: object
0 голосов
/ 02 марта 2020

Не совсем уверен в эффективности кода, но он выполняет свою работу:

uniqueRows = {}

for index, row in df.iterrows():
    duplicateFound = False
    for c_value, uniqueRow in uniqueRows.items():
        if duplicateFound:
            continue
        if len(row['B']) == len(uniqueRow):
            if len(list(set(row['B']) - set(uniqueRow))) == 0:
                print(c_value)
                df.at[index, 'C'] = c_value
                uniqueFound = True

    if not duplicateFound:
        uniqueRows[row['C']] = row['B']

print(df)
print(uniqueRows)

Этот код сначала перебирает ваш фрейм данных. Он имеет логическое значение duplicateFound для каждой строки, которая будет использоваться позже.

Он будет l oop над диктовкой uniqueRows и сначала проверяет, найден ли дубликат. В этом случае он продолжит пропускать вычисления, так как в этом больше нет необходимости.

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

Таким образом, если список пуст, он устанавливает значение из столбца C в этой позиции, используя pandas dataframe at function (это необходимо использовать при переборе по фрейму данных link ). Он устанавливает для переменной unqiueFound значение True, чтобы предотвратить дальнейшие сравнения. Если дубликаты не были найдены, значение uniqueFound все равно будет равно False и будет вызывать добавление к диктанту uniqueRows в конце для l oop перед переходом к следующей строке.

Если у вас есть какие-либо комментарии или улучшения к моему коду, не стесняйтесь обсуждать и надеяться, что этот код поможет вам в вашем проекте!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...