Ответ 1
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
Я хотел бы добавить строку в начало каждого значения в указанном столбце pandas dataframe (элегантно). Я уже понял, как это сделать, и в настоящее время я использую:
df.ix[(df['col'] != False), 'col'] = 'str'+df[(df['col'] != False), 'col']
Кажется, это один из черт неэлегантной вещи - знаете ли вы какой-либо другой способ (который, возможно, также добавляет символ в строки, где этот столбец равен 0 или NaN)?
Если это пока неясно, я бы хотел повернуть:
col
1 a
2 0
в
col
1 stra
2 str0
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
В качестве альтернативы вы также можете использовать команду apply
сочетании с format
который я нахожу немного более читабельным, если, например, также необходимо добавить суффикс или манипулировать самим элементом:
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-string почти такая же быстрая, как решение @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)
Если вы загружаете файл таблицы с помощью dtype=str
или преобразовать тип столбца в строку df['a'] = df['a'].astype(str)
тогда вы можете использовать такой подход:
df['a']= 'col' + df['a'].str[:]
Этот подход позволяет добавлять, добавлять и подстраивать строку из df
.
Работает на Pandas v0.23.4, v0.24.1. Не знаю о более ранних версиях.
Вот несколько "элегантных" решений для вас. Вы можете выяснить, какое решение работает лучше всего, в зависимости от ваших данных, требований к производительности и читабельности. Были предоставлены решения, которые работают для столбцов с чистой строкой, а также обрабатывают общий случай смешанных типов и NaN.
векторизованная конкатенация строк
df = pd.DataFrame({'col': ['a', '5', 'eee']})
df2 = pd.DataFrame({'col': ['a', 5, 'eee', np.nan]})
df
col
0 a
1 5
2 eee
df2
col
0 a
1 5
2 eee
3 NaN
Если ваш столбец (столбцы) полностью строки (то есть, нет NaN или смешанных типов, числовых и т.д.), Решение простое:
'str' + df
col
0 stra
1 str5
2 streee
Чтобы соединить 'str' только с конкретным столбцом,
'str' + df['col']
0 stra
1 str5
2 streee
Name: col, dtype: object
Результат может быть присвоен обратно, либо на месте,
df['col'] = 'str' + df['col']
Или с помощью DataFrame.assign
:
df.assign(col='str' + df['col'])
Если вам нужно обработать отсутствующие данные или смешанные dtypes (например, как в df2
), вы можете использовать Series.isna
для генерации маски для передачи в Series.where
.
u = df2['col'].where(df2['col'].isna(), df2['col'].astype(str))
u
0 a
1 5
2 eee
3 NaN
Name: col, dtype: object
'str' + u
0 stra
1 str5
2 streee
3 NaN
Name: col, dtype: object
df['col'].radd('str')
0 stra
1 str5
2 streee
Name: col, dtype: object
Для смешанных типов /NaNs,
u = df2['col'].where(df2['col'].isna(), df2['col'].astype(str))
u.radd('str')
0 stra
1 str5
2 streee
3 NaN
Name: col, dtype: object
numpy.char.add
/numpy.core.defchararray.add
np.char.add('str', df.col)
# array(['stra', 'str5', 'streee'], dtype='<U11')
df.assign(col=np.char.add('str', df.col))
col
0 stra
1 str5
2 streee
Для смешанных типов и NaN выполните процедуру, описанную выше, с add
:
u = (pd.Series(np.char.add('str', df2['col'].values.astype(str)))
.where(df2['col'].notna()))
df2.assign(col=u)
col
0 stra
1 str5
2 streee
3 NaN
df['col'].map('str{0}'.format)
col
0 stra
1 str5
2 streee
И, для общего случая, используйте
df2['col'].map('str{0}'.format).where(df2['col'].notna())
0 stra
1 str5
2 streee
3 NaN
Name: col, dtype: object
Список Пониманий
Я собираюсь выйти на конечность и сказать, что понимание списка, вероятно, самые быстрые решения здесь. Проблема в том, что строковые операции по своей природе сложнее векторизовать, поэтому большинство "векторизованных" функций панд в основном являются обертками для циклов. Если вам не нужны накладные расходы, вы можете удалить их, написав свои собственные циклы. Я много писал об этом в " Для петель с пандами". Когда мне это нужно? ,
['str' + x for x in df['col']]
# ['stra', 'str5', 'streee']
df.assign(col=['str' + x for x in df['col']])
col
0 stra
1 str5
2 streee
Или, используя str.format
:
df.assign(col=[f'str{x}' for x in df['col']])
col
0 stra
1 str5
2 streee
Эти решения также имеют общий эквивалент:
df2.assign(col=[
'str' + str(x) if pd.notna(x) else np.nan for x in df2['col']])
col
0 stra
1 str5
2 streee
3 NaN
df2.assign(col=[f'str{x}' if pd.notna(x) else np.nan for x in df2['col']])
col
0 stra
1 str5
2 streee
3 NaN
Другое решение с .loc:
df = pd.DataFrame({'col': ['a', 0]})
df.loc[df.index, 'col'] = 'string' + df['col'].astype(str)
Это не так быстро, как решения, описанные выше (> 1 мс на цикл медленнее), но может быть полезно в случае, если вам нужно условное изменение, например:
mask = (df['col'] == 0)
df.loc[df[mask].index, 'col'] = 'string' + df['col'].astype(str)