додайте рядковий префікс до кожного значення в стовпці рядків за допомогою Pandas


119

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

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

Здається, це одне пекло неелегантної речі - чи знаєте ви будь-який інший спосіб (який, можливо, також додає символ до рядків, де стовпець 0 або NaN)?

Якщо це ще не зрозуміло, я хотів би звернутися:

    col 
1     a
2     0

в:

       col 
1     stra
2     str0

Що саме ви запитуєте? будь ласка, напишіть пояснення щодо того, що робить ваш код / ​​бажайте, щоб він це зробив
Райан Сакс

1
Я подумав, що прикладний код дуже зрозумілий середньому користувачеві панд. Я додав приклади використання для вашої зручності.
TheChimera

3
Ваш опис дещо суперечить вашому коду. Що з != Falseбізнесом? Ви хочете додати strдо кожної цінності чи лише деяких?
BrenBarn

до кожного значення, як показано в моїх прикладах фреймів даних.
TheChimera

1
ваш приклад досі трохи незрозумілий, чи хочете чогось подібного df['col'] = 'str' + df['col'].astype(str)?
Роман Пекар

Відповіді:


223
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
спасибі. за інтересів, індекси фреймів даних також підтримують такі рядкові маніпуляції.
тагома

2
Як це зробити, якщо перед об'єднанням повинні бути виконані умови?
ацекабана

1
@tagoma, через 4 роки, так: він також підтримує індекси кадру даних. Ви можете створити новий стовпець і додати до значення індексу: df ['col'] = 'str' + df.index.astype (str)
MEdwin

"astype (str)" може зруйнувати кодування, якщо ви намагаєтесь зберегти файл у підсумку.
Рейн Хашемі

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-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)

той же результат, але шлях повільніше ;-)
Philipp_Kats

1
@Philipp_Kats: Я додав кілька таймінгів, дякую за пропозицію! Здається, f-рядки майже такі ж швидкі; formatдійсно працює гірше. Як ти порівнював?
Клеб

о, гарно! на мій погляд, .applyце завжди або швидше або повільніше, ніж "прямі" векторні операції; навіть якщо вони не повільніші, я вважаю за краще уникати їх там, де це можливо.
Philipp_Kats

@Philipp_Kats: Я погоджуюсь, однак у цьому конкретному випадку я вважаю, що це читає, коли я також додаю суфікс, роблю щось із xсобою тощо, але це лише питання смаку ... :)
Клеб

4

Ви можете використовувати pandas.Series.map:

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

Він застосує слово "str" ​​перед усіма вашими значеннями.


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)

Чому .indexв df[mask].index?
AMC

@AMC, тому що для .loc потрібні показники фрейму даних. Це означає - df [маска] повертає кадр даних, що відповідає умові, а df [маска] .index повертає індекси фрейму даних. Але це правда, що ви можете зробити те ж саме і з df.loc [(df ['col'] == 'a'), 'col'] або df.loc [mask, 'col'].
Лукас

1
тому що для .loc потрібні показники фрейму даних. Якщо df.loc[mask]працює, і це робить, то .indexце зайве, правда?
AMC

@AMC саме :). Я відредагував рішення. Дякую.
Лукас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.