Как преобразовать pandas столбец массивов, удалив значение, полученное из той же строки - PullRequest
1 голос
/ 13 июля 2020

Предположим, у меня есть фрейм данных со столбцом first_name (строка) и другим столбцом name_variations (массив). Как я могу выполнить операцию столбца в массиве name_variations, чтобы я мог удалить любое значение, содержащееся в массиве, которое соответствует значению поля first_name?

Например, вот начальный фрейм данных:

data = {'first_name':  ['Robert',
                    'Richard',
                    'Joseph'],
    'name_variations': [np.array(['Robert', 'Rob', 'Bob']),
                        np.array(['Rich', 'Richard', 'Rick']),
                        np.array(['Joe'])],
    }

df = pd.DataFrame (data, columns = ['first_name','name_variations'])

Это дает такой фрейм данных:

  first_name        name_variations
0     Robert     [Robert, Rob, Bob]
1    Richard  [Rich, Richard, Rick]
2     Joseph                  [Joe]

Я хотел бы преобразовать его так, чтобы Роберт и Ричард были удалены из первых двух значений name_variation (на основе столбца first_name), но третье значение остается прежним.

Желаемый результат:

  first_name name_variations
0     Robert      [Rob, Bob]
1    Richard    [Rich, Rick]
2     Joseph           [Joe]

Редактирование вопроса после правильного ответа Криса на исходный вопрос. Я должен был упомянуть в своем вопросе, что мой фрейм данных довольно большой (1 миллион строк), и я хочу увидеть, возможна ли векторизованная операция, а не с помощью apply, которая работает медленнее.

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Вот способ использования explode:

df['name_variations'] = (df.explode('name_variations')
                           .query('first_name != name_variations')
                           .groupby(level=0)['name_variations']
                           .agg(list))

Вывод:

  first_name name_variations
0     Robert      [Rob, Bob]
1    Richard    [Rich, Rick]
2     Joseph           [Joe]

Другой способ использования вложенного списка

df['name_variations'] = [[i for i in x if (i != df['first_name']).all()] for x in df['name_variations']]

Время:

%timeit df['name_variations'] = df.explode('name_variations').query('first_name != name_variations').groupby(level=0)['name_variations'].agg(list)
10.1 ms ± 294 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df.apply(lambda row: [x for x in row['name_variations'] if x!= row['first_name']], axis=1)
2.33 ms ± 68.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df['name_variations'] = [[i for i in x if (i != df['first_name']).all()] for x in df['name_variations']]
1.67 ms ± 66.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1 голос
/ 13 июля 2020
df['name_variations'] = df.apply(lambda row: [x for x in row['name_variations'] if x!= row['first_name']], axis=1)

или

df = df.explode('name_variations')
df[df['first_name']!=df['name_variations']].groupby('first_name')['name_variations'].apply(list).reset_index()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...