Добавить столбец в фрейм данных из списка

95

У меня есть фрейм данных с такими столбцами:

A   B   C  
0   
4
5
6
7
7
6
5

В Возможный диапазон значений в только от 0 до 7 .

Кроме того, у меня есть список из 8 таких элементов:

List=[2,5,6,8,12,16,26,32]  //There are only 8 elements in this list

Если элемент в столбце A равен n , мне нужно вставить n- й элемент из списка в новый столбец, скажем «D».

Как я могу сделать это за один раз, не перебирая весь фрейм данных?

Результирующий фрейм данных будет выглядеть так:

A   B   C   D
0           2
4           12
5           16
6           26
7           32
7           32
6           26
5           16

Примечание. Фрейм данных огромен, и последним вариантом является итерация. Но я также могу расположить элементы в «Списке» в любой другой структуре данных, например, в dict, если это необходимо.

грива
источник
1
Думаю, вам нужен пример игрушки (поменьше) с желаемым результатом. Это звучит немного расплывчато.
Энди Хайден
11
Никогда не называйте переменную «Список». На любом языке.
lucid_dreamer 09

Ответы:

51

IIUC, если вы превратите свой (к сожалению, названный) Listв файл ndarray, вы можете просто проиндексировать его естественным образом.

>>> import numpy as np
>>> m = np.arange(16)*10
>>> m[df.A]
array([  0,  40,  50,  60, 150, 150, 140, 130])
>>> df["D"] = m[df.A]
>>> df
    A   B   C    D
0   0 NaN NaN    0
1   4 NaN NaN   40
2   5 NaN NaN   50
3   6 NaN NaN   60
4  15 NaN NaN  150
5  15 NaN NaN  150
6  14 NaN NaN  140
7  13 NaN NaN  130

Здесь я построил новый m, но если вы его используете m = np.asarray(List), должно работать то же самое: значения в df.Aбудут выбирать соответствующие элементы m.


Обратите внимание, что если вы используете старую версию numpy, вам, возможно, придется использовать m[df.A.values]вместо нее - в прошлом numpyне очень хорошо работал с другими, и некоторые рефакторинги pandasвызывали некоторые головные боли. Сейчас все стало лучше.

DSM
источник
Привет @DSM. Я понимаю, о чем вы говорите, но получаю эту ошибку: Traceback (most recent call last): File "./b.py", line 24, in <module> d["D"] = m[d.A] IndexError: unsupported iterator index
mane
1
@mane: urf, это старый numpyбаг. Вам подходит d["D"] = m[d.A.values]?
DSM
277

Просто назначьте список напрямую:

df['new_col'] = mylist

Альтернатива
Преобразуйте список в серию или массив, а затем назначьте:

se = pd.Series(mylist)
df['new_col'] = se.values

или

df['new_col'] = np.array(mylist)
воробей
источник
3
pykernel_launcher.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """Entry point for launching an IPython kernel.
Илья Русин
@sparrow будет использовать pd.Seriesэффект dtype? Я имею в виду, оставит ли он числа с плавающей запятой как числа с плавающей точкой, а строки как строки? Или элементы в списке по умолчанию будут строками?
3kstc
2
@IlyaRusin, это ложное срабатывание, которое в этом случае можно игнорировать. Для получения дополнительной информации: stackoverflow.com/questions/20625582/…
sparrow
1
Это можно упростить до: df ['new_col'] = pd.Series (mylist) .values
smartse
16

Решение, улучшающее отличное решение от @sparrow.

Пусть df будет вашим набором данных и mylist список со значениями, которые вы хотите добавить во фрейм данных.

Предположим, вы хотите называть свой новый столбец просто new_column

Сначала сделайте список в серии:

column_values = pd.Series(mylist)

Затем используйте функцию вставки, чтобы добавить столбец. Эта функция имеет то преимущество, что вы можете выбрать, в каком положении вы хотите разместить столбец. В следующем примере мы разместим новый столбец в первой позиции слева (установив loc = 0)

df.insert(loc=0, column='new_column', value=column_values)
Сальваторе Косентино
источник
Это не сработает, если вы изменили свои индексы df на что-то другое, кроме 1,2,3 ... в этом случае вам нужно добавить между строк: column_values.index = df.index
Guy s
8

Сначала давайте создадим фрейм данных, который у вас был, я проигнорирую столбцы B и C, поскольку они не имеют отношения к делу.

df = pd.DataFrame({'A': [0, 4, 5, 6, 7, 7, 6,5]})

И желаемое отображение:

mapping = dict(enumerate([2,5,6,8,12,16,26,32]))

df['D'] = df['A'].map(mapping)

Выполнено!

print df

Выход:

   A   D
0  0   2
1  4  12
2  5  16
3  6  26
4  7  32
5  7  32
6  6  26
7  5  16
Фил Купер
источник
1
Я думаю, ОП уже знает, как это сделать. По моему мнению, проблема строится Dиз элементов Aи List(«Если элемент в столбце A равен n, мне нужно вставить n-й элемент из списка в новый столбец, скажем,« D »»)
DSM
SO превратился в какое-то состояние F (* и няни. Спасибо @DSM за комментарий, но я не мог исправить сообщение, пока он не был рассмотрен коллегами. Затем он был отклонен, потому что он был слишком быстрым. А затем я был возможность коллеги проверить мою собственную правку. а потом уже слишком поздно, потому что худший (ИМХО) ответ был «принят». ТАК действительно есть несколько мета-няней, которые менее чем полезны !!!!
Фил Купер
Ну, я не могу говорить за няню, но вы обнаружите, что ваш подход примерно на порядок медленнее на длинных массивах. В остальном, конечно, выбор между np.array(List)[df.A]и df["A"].map(dict(enumerate(List)))- это в основном вопрос предпочтений.
DSM
Привет, Фил, я видел только ваше решение и комментарий DSM, но никогда не возвращался к нему, так как решение DSM работало для меня нормально. Но теперь, глядя на ваше решение, оно тоже работает. Я запустил решение DSM для своего набора данных из примерно 200 тыс. Записей, и оно выполняется за пару секунд со всеми остальными расчетами, которые у меня есть. Я новичок в python-pandas и лично не искал ничего элегантного или замечательного; все, что работало, было хорошо. Но, честно говоря, спасибо за решение.
mane
2

Старый вопрос; но я всегда стараюсь использовать самый быстрый код!

У меня был огромный список из 69 миллионов uint64. np.array () был для меня самым быстрым.

df['hashes'] = hashes
Time spent: 17.034842014312744

df['hashes'] = pd.Series(hashes).values
Time spent: 17.141014337539673

df['key'] = np.array(hashes)
Time spent: 10.724546194076538
Мехди
источник