Подтвердить что ты не робот

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

Я хотел бы добавить строку в начало каждого значения в указанном столбце 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
4b9b3361

Ответ 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

Ответ 2

В качестве альтернативы вы также можете использовать команду 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)

Ответ 3

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

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

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

Ответ 4

Вот несколько "элегантных" решений для вас. Вы можете выяснить, какое решение работает лучше всего, в зависимости от ваших данных, требований к производительности и читабельности. Были предоставлены решения, которые работают для столбцов с чистой строкой, а также обрабатывают общий случай смешанных типов и 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

Series.radd

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

Series.map и str.format

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

Ответ 5

Другое решение с .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)