tambahkan awalan string ke setiap nilai dalam kolom string menggunakan Pandas

119

Saya ingin menambahkan string ke awal setiap nilai di kolom kata dari bingkai data panda (dengan elegan). Saya sudah menemukan cara untuk melakukan ini dan saat ini saya menggunakan:

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

Ini sepertinya hal yang sangat tidak elegan untuk dilakukan - apakah Anda tahu cara lain (yang mungkin juga menambahkan karakter ke baris di mana kolom itu adalah 0 atau NaN)?

Jika ini masih belum jelas, saya ingin membalik:

    col 
1     a
2     0

ke:

       col 
1     stra
2     str0
TheChymera
sumber
Apa sebenarnya yang kamu tanyakan? harap tulis penjelasan tentang apa yang dilakukan / diinginkan kode Anda
Ryan Saxe
1
Saya pikir apa yang dilakukan kode contoh sangat jelas bagi pengguna panda pada umumnya. Saya telah menambahkan contoh kasus penggunaan untuk kenyamanan Anda.
TheChymera
3
Deskripsi Anda agak bertentangan dengan kode Anda. Ada apa dengan != Falsebisnis ini? Apakah Anda ingin menambah strsetiap nilai atau hanya beberapa?
BrenBarn
ke setiap nilai, seperti yang ditunjukkan dalam contoh kerangka data saya.
TheChymera
1
contoh Anda masih agak tidak jelas, apakah Anda menginginkan sesuatu seperti df['col'] = 'str' + df['col'].astype(str)?
Roman Pekar

Jawaban:

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

Contoh:

>>> 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
Roman Pekar
sumber
1
Terima kasih. Jika menarik, indeks bingkai data juga mendukung manipulasi string tersebut.
tagoma
2
Bagaimana saya melakukan ini jika kondisi harus dipenuhi sebelum penggabungan?
acecabana
1
@tagoma, setelah 4 tahun, Ya: itu juga mendukung indeks dataframe. Anda dapat membuat kolom baru dan menambahkan ke nilai indeks sebagai: df ['col'] = 'str' + df.index.astype (str)
MEdwin
"astype (str)" dapat merusak pengkodean jika Anda mencoba menyimpan ke file pada akhirnya.
Raein Hashemi
2
Ketika saya mencoba ini serta pendekatan lainnya, saya mendapatkan SettingWithCopyWarning. Apakah ada cara untuk menghindarinya?
Madan Ivan
13

Sebagai alternatif, Anda juga dapat menggunakan applykombinasi dengan format(atau lebih baik dengan f-string) yang menurut saya sedikit lebih mudah dibaca jika salah satu misalnya ingin menambahkan sufiks atau memanipulasi elemen itu sendiri:

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

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

yang juga menghasilkan keluaran yang diinginkan:

    col
0  stra
1  str0

Jika Anda menggunakan Python 3.6+, Anda juga dapat menggunakan f-string:

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

menghasilkan keluaran yang sama.

Versi f-string hampir secepat solusi @ 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)

Menggunakan format, bagaimanapun, memang jauh lebih lambat:

%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
sumber
hasil yang sama, tetapi jauh lebih lambat ;-)
Philipp_Kats
1
@Philipp_Kats: Saya menambahkan beberapa pengaturan waktu, terima kasih atas sarannya! Tampaknya f-string hampir sama cepatnya; formatmemang berkinerja lebih buruk. Bagaimana Anda membandingkan?
Cleb
Oh bagus! dalam pemahaman saya .applyselalu lebih cepat atau lebih lambat daripada operasi vektor "langsung"; bahkan jika tidak lebih lambat, saya lebih suka menghindarinya jika memungkinkan.
Philipp_Kats
@Philipp_Kats: Saya setuju, namun, dalam kasus khusus ini saya merasa lebih mudah dibaca ketika saya juga menambahkan sufiks, melakukan sesuatu dengan xsendirinya, dll., Tetapi itu hanya masalah selera ... :)
Cleb
4

Anda dapat menggunakan pandas.Series.map:

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

Ini akan menerapkan kata "str" ​​sebelum semua nilai Anda.

Boxtell
sumber
3

Jika Anda memuat file tabel Anda dtype=str
atau mengonversi jenis kolom menjadi string df['a'] = df['a'].astype(str)
maka Anda dapat menggunakan pendekatan seperti itu:

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

Pendekatan ini memungkinkan string tambahan, penambahan, dan subset dari df.
Bekerja pada Pandas v0.23.4, v0.24.1. Tidak tahu tentang versi sebelumnya.

Vasyl Vaskivskyi
sumber
0

Solusi lain dengan .loc:

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

Ini tidak secepat solusi di atas (> 1ms per loop lebih lambat) tetapi mungkin berguna jika Anda membutuhkan perubahan bersyarat, seperti:

mask = (df['col'] == 0)
df.loc[mask, 'col'] = 'string' + df['col'].astype(str)
Lukas
sumber
Mengapa .indexmasuk df[mask].index?
AMC
@AMC karena untuk .loc Anda memerlukan indeks dari dataframe. Artinya - df [mask] mengembalikan dataframe yang cocok dengan kondisi dan df [mask] .index mengembalikan indeks dari dataframe. Tetapi memang benar bahwa Anda dapat melakukan hal yang sama dengan df.loc [(df ['col'] == 'a'), 'col'] atau df.loc [mask, 'col'] juga.
Lukas
1
karena untuk .loc Anda membutuhkan indeks dari dataframe. Jika df.loc[mask]berhasil, dan berhasil, maka itu tidak .indexberguna, bukan?
AMC
@AMC tepatnya :). Saya telah mengedit solusinya. Terima kasih.
Lukas