0

Pandas: Одновременное присвоение нескольких *новых* столбцов

1

У меня есть DataFrame df, содержащий столбец с метками для каждой строки (в дополнение к некоторым соответствующим данным для каждой строки). У меня есть словарь labeldict, у которого ключи соответствуют возможным меткам, а значения представляют собой 2-кортежи информации, связанной с этой меткой. Мне нужно добавить два новых столбца в мой DataFrame, по одному для каждой части 2-кортежа, соответствующего метке для каждой строки.

Вот мой код:

import pandas as pd
import numpy as np

np.random.seed(1)
n = 10

labels = list('abcdef')
colors = ['red', 'green', 'blue']
sizes = ['small', 'medium', 'large']

labeldict = {c: (np.random.choice(colors), np.random.choice(sizes)) for c in labels}

df = pd.DataFrame({'label': np.random.choice(labels, n), 
                   'somedata': np.random.randn(n)})

Я могу получить желаемый результат, выполнив следующий код:

df['color'], df['size'] = zip(*df['label'].map(labeldict))
print(df)

Но как я могу сделать это, если не хочу вручную вводить названия двух столбцов с левой стороны присваивания? То есть, как я могу создать несколько новых столбцов динамически? Например, если бы у меня были 10-кортежи в labeldict вместо 2-кортежей, это было бы настоящим утомлением. Вот несколько попыток, которые не работают:

# задать список атрибутов для дальнейшего использования
attrlist = ['color', 'size']

# неработающая идея 1
df[attrlist] = zip(*df['label'].map(labeldict))

# неработающая идея 2
df.loc[:, attrlist] = zip(*df['label'].map(labeldict))

Хотя это работает, это кажется не очень элегантным решением:

for a in attrlist:
    df[a] = 0
df[attrlist] = zip(*df['label'].map(labeldict))

Есть ли более хорошие решения?

4 ответ(ов)

0

Вы можете использовать метод merge вместо этого:

>>> ld = pd.DataFrame(labeldict).T
>>> ld.columns = ['color', 'size']
>>> ld.index.name = 'label'
>>> df.merge(ld.reset_index(), on='label')
  label  somedata  color    size
0     b  1.462108    red  medium
1     c -2.060141  green   small
2     c  1.133769  green   small
3     c  0.042214  green   small
4     e -0.322417    red  medium
5     e -1.099891    red  medium
6     e -0.877858    red  medium
7     e  0.582815    red  medium
8     f -0.384054    red   large
9     d -0.172428    red  medium

Таким образом вы сможете объединить ваши данные с помощью общего столбца label.

0

Вместо того чтобы использовать labeldict, вы можете преобразовать эту информацию в DataFrame и затем объединить его с вашим оригинальным DataFrame. Вот пример того, как это можно сделать:

import pandas as pd
import numpy as np

# Пример данных
labels = ['a', 'b', 'a', 'b', 'b', 'd', 'b', 'd', 'e', 'c']
colors = ['red', 'blue', 'green']
sizes = ['small', 'medium', 'large']

# Создание DataFrame с цветами и размерами
labeldf = pd.DataFrame([(np.random.choice(colors), np.random.choice(sizes)) for c in labels], columns=['color', 'size'], index=labels)

# Ваш оригинальный DataFrame
df = pd.DataFrame({
    'label': labels,
    'somedata': np.random.randn(len(labels))
})

# Объединение DataFrame по метке
result = df.join(labeldf, on='label')

print(result)

В результате вы получите DataFrame, в котором будет объединена информация как из вашего оригинального DataFrame, так и из labeldf, что позволяет более удобно работать с данными:

  label  somedata  color    size
0     a -1.709973    red  medium
1     b  0.099109   blue  medium
2     a -0.427323    red  medium
3     b  0.474995   blue  medium
4     b -2.819208   blue  medium
5     d -0.998888    red   small
6     b  0.713357   blue  medium
7     d  0.331989    red   small
8     e -0.906240  green   large
9     c -0.501916   blue   large

Таким образом, использование DataFrame и методов объединения в Pandas делает ваш код более читаемым и упрощает работу с данными.

0

Если вы хотите добавить несколько столбцов в DataFrame в рамках цепочки методов, вы можете использовать apply. Первым шагом необходимо создать функцию, которая преобразует строку, представленную как Series, в нужный вам формат. Затем можно вызвать apply, чтобы применить эту функцию к каждой строке.

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

def append_label_attributes(row: pd.Series, labelmap: dict) -> pd.Series:
    result = row.copy()
    result['color'] = labelmap[result['label']][0]
    result['size'] = labelmap[result['label']][1]
    return result

Далее вы можете создать DataFrame и применить функцию через apply:

df = (
    pd.DataFrame(
        {
            'label': np.random.choice(labels, n),
            'somedata': np.random.randn(n)
        }
    )
    .apply(append_label_attributes, axis='columns', labelmap=labeldict)
)

Таким образом, вы сможете добавить новые столбцы color и size к вашему DataFrame, используя данные из labeldict.

0

Это должно сработать:

df[['color', 'size']] = list(df['label'].apply(labeldict))

Таким образом, вы применяете функцию labeldict к каждому элементу столбца 'label' и сохраняете результаты в новые столбцы 'color' и 'size' вашего DataFrame df. Убедитесь, что функция labeldict возвращает результаты в виде списков или кортежей с двумя элементами. Если все настроено правильно, код должен работать корректно.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь