добавить префикс строки к каждому значению в столбце строки с помощью Pandas

119

Я хотел бы добавить строку в начало каждого значения в указанном столбце фрейма данных pandas (элегантно). Я уже понял, как это сделать, и сейчас использую:

df.ix[(df['col'] != False), 'col'] = 'str'+df[(df['col'] != False), 'col']

Это кажется чертовски неэлегантным делом - знаете ли вы какой-либо другой способ (который, возможно, также добавляет символ в строки, в которых этот столбец равен 0 или NaN)?

Если это пока неясно, хочу обратить внимание:

    col 
1     a
2     0

в:

       col 
1     stra
2     str0
TheChymera
источник
Что именно вы спрашиваете? пожалуйста, напишите объяснение того, что делает / желает ваш код
Райан Сакс
1
Я думал, что пример кода очень понятен среднему пользователю pandas. Для вашего удобства я добавил примеры использования.
TheChymera
3
Ваше описание несколько расходится с вашим кодом. Что там с != Falseбизнесом? Вы хотите добавить strк каждой ценности или только к некоторым?
BrenBarn
для каждого значения, как показано в моих примерах фреймов данных.
TheChymera
1
ваш пример все еще немного неясен, вы хотите что-то вроде df['col'] = 'str' + df['col'].astype(str)?
Роман Пекар

Ответы:

226
df['col'] = 'str' + df['col'].astype(str)

Пример:

>>> df = pd.DataFrame({'col':['a',0]})
>>> df
  col
0   a
1   0
>>> df['col'] = 'str' + df['col'].astype(str)
>>> df
    col
0  stra
1  str0
Роман Пекар
источник
1
Спасибо. если интересно, индексы фреймов данных также поддерживают такие манипуляции со строками.
tagoma
2
Как это сделать, если перед объединением должны быть выполнены условия?
acecabana
1
@tagoma, через 4 года, да: он также поддерживает индексы фреймов данных. Вы можете создать новый столбец и добавить его к значению индекса следующим образом: df ['col'] = 'str' + df.index.astype (str)
MEdwin
"astype (str)" может испортить кодировку, если в конце вы попытаетесь сохранить в файл.
Raein Hashemi
2
Когда я пробую этот, а также любой другой подход, я получаю SettingWithCopyWarning. Есть ли способ избежать этого?
Мадан Иван
13

В качестве альтернативы вы также можете использовать applyкомбинацию с format(или лучше с f-строками), которую я считаю немного более читаемой, если, например, кто-то также хочет добавить суффикс или манипулировать самим элементом:

df = pd.DataFrame({'col':['a', 0]})

df['col'] = df['col'].apply(lambda x: "{}{}".format('str', x))

что также дает желаемый результат:

    col
0  stra
1  str0

Если вы используете Python 3.6+, вы также можете использовать f-строки:

df['col'] = df['col'].apply(lambda x: f"str{x}")

дающий тот же результат.

Версия с f-строкой почти так же быстро, как решение @ RomanPekar (python 3.6.4):

df = pd.DataFrame({'col':['a', 0]*200000})

%timeit df['col'].apply(lambda x: f"str{x}")
117 ms ± 451 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit 'str' + df['col'].astype(str)
112 ms ± 1.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Используя format, однако, на самом деле гораздо медленнее:

%timeit df['col'].apply(lambda x: "{}{}".format('str', x))
185 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Cleb
источник
тот же результат, но намного медленнее ;-)
Philipp_Kats
1
@Philipp_Kats: Я добавил тайминги, спасибо за предложение! Кажется, что фа-струны почти такие же быстрые; formatдействительно работает хуже. Как сравнивали?
Cleb
о, классно! в моем понимании .applyвсегда либо так же быстро, либо медленнее, чем «прямые» векторизованные операции; даже если они не медленнее, я предпочитаю по возможности избегать их.
Philipp_Kats
@Philipp_Kats: Я согласен, однако, в данном случае , я считаю его более понятным , когда я добавить суффикс, сделать что - то с xсобой и т.д., но это всего лишь дело вкуса ... :)
Cleb
4

Вы можете использовать pandas.Series.map:

df['col'].map('str{}'.format)

Он будет применять слово "str" ​​перед всеми вашими значениями.

Boxtell
источник
3

Если вы загружаете файл таблицы dtype=str
или конвертируете тип столбца в строку, df['a'] = df['a'].astype(str)
вы можете использовать такой подход:

df['a']= 'col' + df['a'].str[:]

Этот подход позволяет добавлять строки в начало, добавление и подмножество df.
Работает на Pandas v0.23.4, v0.24.1. Не знаю о более ранних версиях.

Василий Васьковский
источник
0

Другое решение с .loc:

df = pd.DataFrame({'col': ['a', 0]})
df.loc[df.index, 'col'] = 'string' + df['col'].astype(str)

Это не так быстро, как решения выше (> 1 мс на цикл медленнее), но может быть полезно в случае, если вам нужно условное изменение, например:

mask = (df['col'] == 0)
df.loc[mask, 'col'] = 'string' + df['col'].astype(str)
Lukas
источник
Почему .indexв df[mask].index?
AMC
@AMC, потому что для .loc вам нужны индексы фрейма данных. Это означает, что - df [mask] возвращает фрейм данных, соответствующий условию, а df [mask] .index возвращает индексы фрейма данных. Но верно то, что вы можете сделать то же самое с df.loc [(df ['col'] == 'a'), 'col'] или df.loc [mask, 'col'] тоже.
Лукас,
1
потому что для .loc вам нужны индексы фрейма данных. Если df.loc[mask]работает, и работает, то .indexлишнее, правда?
AMC,
@AMC точно :). Я отредактировал решение. Спасибо.
Лукас,