เพิ่มคำนำหน้าสตริงให้กับแต่ละค่าในคอลัมน์สตริงโดยใช้ 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

ถามอะไรกันแน่? โปรดเขียนคำอธิบายเกี่ยวกับสิ่งที่รหัสของคุณทำ / ต้องการ
Ryan Saxe

1
ฉันคิดว่าโค้ดตัวอย่างนั้นชัดเจนมากสำหรับผู้ใช้แพนด้าทั่วไป ฉันได้เพิ่มตัวอย่างกรณีการใช้งานเพื่อความสะดวกของคุณ
TheChymera

3
คำอธิบายของคุณค่อนข้างขัดแย้งกับรหัสของคุณ เกิดอะไรขึ้นกับ!= Falseธุรกิจ? คุณต้องการเพิ่มstrทุกค่าหรือเพียงบางส่วน?
BrenBarn

ทุกค่าดังที่แสดงในดาต้าเฟรมตัวอย่างของฉัน
TheChymera

1
ตัวอย่างของคุณยังไม่ชัดเจนคุณต้องการอะไรdf['col'] = 'str' + df['col'].astype(str)หรือไม่?
Roman Pekar

คำตอบ:


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 มีวิธีหลีกเลี่ยงหรือไม่?
Madan Ivan

13

อีกทางเลือกหนึ่งคุณสามารถใช้การapplyรวมกับformat(หรือดีกว่ากับ f-strings) ซึ่งฉันพบว่าอ่านได้ง่ายกว่าเล็กน้อยหากต้องการเพิ่มคำต่อท้ายหรือจัดการองค์ประกอบเอง:

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-strings:

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ประสิทธิภาพแย่ลงแน่นอน คุณเปรียบเทียบได้อย่างไร?
Cleb

ดี! ในความเข้าใจของฉัน.applyมักจะเร็วหรือช้ากว่าการดำเนินการแบบเวกเตอร์ "โดยตรง" เสมอ แม้ว่าจะไม่ช้ากว่า แต่ฉันก็ชอบที่จะหลีกเลี่ยงเมื่อเป็นไปได้
Philipp_Kats

@Philipp_Kats: ฉันเห็นด้วยอย่างไรก็ตามในกรณีนี้ฉันพบว่ามันอ่านได้ง่ายขึ้นเมื่อฉันเพิ่มคำต่อท้ายทำอะไรกับxตัวเอง ฯลฯ แต่นั่นเป็นเรื่องของรสนิยม ... :)
Cleb

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)

วิธีนี้ไม่เร็วเท่าวิธีแก้ปัญหาด้านบน (> 1ms ต่อลูปช้าลง) แต่อาจมีประโยชน์ในกรณีที่คุณต้องการการเปลี่ยนแปลงตามเงื่อนไขเช่น:

mask = (df['col'] == 0)
df.loc[mask, 'col'] = 'string' + df['col'].astype(str)

ทำไม.indexในdf[mask].index?
AMC

@AMC เพราะสำหรับ. loc คุณต้องการดัชนีของดาต้าเฟรม หมายความว่า - df [mask] ส่งคืน dataframe ที่ตรงกับเงื่อนไขและ df [mask] .index จะส่งกลับดัชนีของ dataframe แต่ก็เป็นเรื่องจริงที่คุณสามารถทำเช่นเดียวกันกับ df.loc [(df ['col'] == 'a'), 'col'] หรือ df.loc [mask, 'col'] ได้เช่นกัน
Lukas

1
เพราะสำหรับ. loc คุณต้องการดัชนีของ dataframe ถ้าใช้df.loc[mask]งานได้และเป็นเช่นนั้นสิ่งที่.indexฟุ่มเฟือยใช่ไหม?
AMC

@AMC เป๊ะ :). ฉันแก้ไขโซลูชันแล้ว ขอบคุณ.
Lukas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.