φυβλαςのβλογ
บล็อกของ phyblas



จัดการข้อมูลด้วย pandas เบื้องต้น บทที่ ๑๗: การจัดการกับข้อมูลสายอักขระ
เขียนเมื่อ 2016/09/25 16:09
เมธอด map และ apply ที่พูดถึงในบทที่ ๙ นั้นทำให้สามารถจัดการกับข้อมูลภายในตารางพร้อมกันแบบเป็นกลุ่มได้อย่างง่ายดาย

แต่สำหรับข้อมูลที่เป็นสายอักขระแล้วมีคำสั่งอื่นๆอีกจำนวนหนึ่งที่ช่วยให้การจัดการข้อมูลง่ายขึ้นไปอีก จึงอาจจะน่าเรียนรู้เพิ่มเติมเอาไว้สักหน่อย

งานที่เกี่ยวกับสายอักขระจะทำโดยเติม .str ต่อจากชื่อตัวแปรซีรีส์ แล้วตามด้วยชื่อเมธอดต่างๆ



การคัดเอาอักษรบางส่วนจากในแต่ละแถว
เติม .str แล้วตามด้วย [] เพื่อเข้าถึงสายอักขระภายในได้เหมือนกับสายอักขระทั่วไป

ตัวอย่าง
import pandas as pd
pokemon = pd.Series([
        'ฟุชิงิดาเนะ','ฟุชิงิโซว','ฟุชิงิบานะ',
        'ฮิโตคาเงะ','ลิซาร์โด','ลิซาร์ดอน',
        'เซนิงาเมะ','คาเมล','คาเม็กซ์'],
    index=[1,2,3,4,5,6,7,8,9])
print(pokemon)



ได้
1    ฟุชิงิดาเนะ
2      ฟุชิงิโซว
3     ฟุชิงิบานะ
4      ฮิโตคาเงะ
5       ลิซาร์โด
6      ลิซาร์ดอน
7      เซนิงาเมะ
8          คาเมล
9       คาเม็กซ์
dtype: object

ลองดูอักษรตัวแรกถึงตัวที่ ๖
print(list(pokemon.str[:6]))
# มีค่าเท่ากับ pokemon.apply(lambda x:x[:6])

ได้
['ฟุชิงิ', 'ฟุชิงิ', 'ฟุชิงิ', 'ฮิโตคา', 'ลิซาร์', 'ลิซาร์', 'เซนิงา', 'คาเมล', 'คาเม็ก']

อนึ่ง ผลที่ได้ออกมาจริงๆนั้นเป็นซีรีส์เหมือนเดิม แต่ในที่นี้เพื่อประหยัดพื้นที่ขอแปลงเป็นลิสต์ ตัวอย่างถัดๆไปก็เช่นเดียวกัน



หาความยาวของสายอักขระ
สามารถหาความยาวของสายอักขระได้ด้วยเมธอด str.len เช่น
print(list(pokemon.str.len()))
# เท่ากับ pokemon.apply(lambda x:len(x))

ได้
[11, 9, 10, 9, 8, 9, 9, 5, 8]



เติมสายอักขระให้ยาวตามที่ต้องการ
เมธอด str.pad มีไว้สำหรับเติมช่องว่างให้สายอักขระเพื่อให้มีความยาวรวมตามต้องการ โดยใส่จำนวนที่ต้องการไปเป็นอาร์กิวเมนต์ตัวแรก และตามด้วยตำแหน่งที่บอกว่าจะเอาตัวหนังสือที่มีอยู่เดิมวางไว้ซ้ายหรือขวาหรือกลาง (left right center)

กรณีที่เลือกตรงกลางอาจใช้เมธอด str.center แทนก็ได้
print(list(pokemon.str.pad(12)))
print(list(pokemon.str.pad(12,'right')))
print(list(pokemon.str.center(12)))

ได้
[' ฟุชิงิดาเนะ', '   ฟุชิงิโซว', '  ฟุชิงิบานะ', '   ฮิโตคาเงะ', '    ลิซาร์โด', '   ลิซาร์ดอน', '   เซนิงาเมะ', '       คาเมล', '    คาเม็กซ์']
['ฟุชิงิดาเนะ ', 'ฟุชิงิโซว   ', 'ฟุชิงิบานะ  ', 'ฮิโตคาเงะ   ', 'ลิซาร์โด    ', 'ลิซาร์ดอน   ', 'เซนิงาเมะ   ', 'คาเมล       ', 'คาเม็กซ์    ']
['ฟุชิงิดาเนะ ', ' ฟุชิงิโซว  ', ' ฟุชิงิบานะ ', ' ฮิโตคาเงะ  ', '  ลิซาร์โด  ', ' ลิซาร์ดอน  ', ' เซนิงาเมะ  ', '   คาเมล    ', '  คาเม็กซ์  ']



นำสายอักขระมาต่อกันทั้งหมด
สามารถนำสายอักขระจากทุกแถวมาต่อกันได้ด้วยเมธอด str.cat สามารถใส่คีย์เวิร์ด sep เพื่อกำหนดคำที่จะใช้คั่นระหว่างแต่ละตัวที่รวม
print(pokemon.str.cat())
print(pokemon.str.cat(sep='|'))

ได้
ฟุชิงิดาเนะฟุชิงิโซวฟุชิงิบานะฮิโตคาเงะลิซาร์โดลิซาร์ดอนเซนิงาเมะคาเมลคาเม็กซ์
ฟุชิงิดาเนะ|ฟุชิงิโซว|ฟุชิงิบานะ|ฮิโตคาเงะ|ลิซาร์โด|ลิซาร์ดอน|เซนิงาเมะ|คาเมล|คาเม็กซ์



เมธอดที่ใช้กับ regex
มีเมธอดมากมายที่ใช้เรกูลาร์เอ็กซ์เพรชชัน (ต่อไปจะเรียกสั้นๆว่า regex)

เรื่องเกี่ยวกับ regex นั้นได้เคยเขียนถึงไว้แล้ว อ่านได้ใน https://phyblas.hinaboshi.com/20160922

สำหรับการหาว่าสายอักขระมีอักษรหรือข้อความที่ต้องการอยู่หรือไม่อาจใช้เมธอด str.contains

เช่น หาว่ามีคำที่มีสระโออยู่หรือไม่
print(list(pokemon.str.contains('โ[ก-ฮ]')))
# ได้ [False, True, False, True, True, False, False, False, False]

หากต้องการค้นหาว่าขึ้นต้นด้วยตัวที่ต้องการหรือไม่ก็ใช้ str.match

เช่น ลองหาว่าคำไหนขึ้นต้นด้วย ก-ม บ้าง
print(list(pokemon.str.match('[ก-ม]')))
# ได้ [True, True, True, False, False, False, False, True, True]

หากต้องการให้แสดงผลการค้นหาทั้งหมดที่เจอก็ใช้ str.findall

เช่น หาคำที่เป็นสระอาหรือเอะ
print(pokemon.str.findall('เ?[ก-ฮ][าะ]'))
# ได้ [['ดา', 'เนะ'], [], ['บา', 'นะ'], ['คา', 'เงะ'], ['ซา'], ['ซา'], ['งา', 'เมะ'], ['คา'], ['คา']]

หากต้องการนับจำนวนผลการค้นหาที่เจอก็ใช้ str.count

เช่น นับจำนวนพยัญชนะในคำ
print(list(pokemon.str.count('[ก-ฮ]')))
# ได้ [5, 5, 5, 4, 4, 6, 4, 3, 4]

หากต้องการค้นหาเพื่อแทนที่ส่วนที่ค้นเจอก็ใช้ str.replace เช่น
print(list(pokemon.str.replace('า','a')))
# ได้ ['ฟุชิงิดaเนะ', 'ฟุชิงิโซว', 'ฟุชิงิบaนะ', 'ฮิโตคaเงะ', 'ลิซaร์โด', 'ลิซaร์ดอน', 'เซนิงaเมะ', 'คaเมล', 'คaเม็กซ์']

หากต้องการแยกข้อความโดยอาศัยตัวคั่นก็ใช้ str.split

เช่นแยกเมื่อเจอสระอะหรืออา
print(list(pokemon.str.split('[าะ]')))
# ได้ [['ฟุชิงิด', 'เน', ''], ['ฟุชิงิโซว'], ['ฟุชิงิบ', 'น', ''], ['ฮิโตค', 'เง', ''], ['ลิซ', 'ร์โด'], ['ลิซ', 'ร์ดอน'], ['เซนิง', 'เม', ''], ['ค', 'เมล'], ['ค', 'เม็กซ์']]

ผลการแยกปกติแล้วจะอยู่ในรูปลิสต์ แต่ถ้าใส่คีย์เวิร์ด expand=True ก็จะอยู่ในรูปของเดตาเฟรม
print(pokemon.str.split('[ะ-๙]',expand=True))

ได้
  0 1 2 3 4 5 6
1    
2   ซว None None
3   None
4   ตค     None
5   None None
6 ดอน None None None
7   ซน     None
8   มล None None None None
9   กซ   None None

ส่วน str.extract จะเป็นการแยกข้อความตามกลุ่มก้อนที่ระบุด้วยวงเล็บ () ใน regex

เช่น
print(pokemon.str.extract('(..)(.{3,4})(.*)',expand=True))

ได้
  0 1 2
1 ฟุ ชิงิ ดาเนะ
2 ฟุ ชิงิ โซว
3 ฟุ ชิงิ บานะ
4 ฮิ โตคา เงะ
5 ลิ ซาร์ โด
6 ลิ ซาร์ ดอน
7 เซ นิงา เมะ
8 คา เมล  
9 คา เม็ก ซ์

ถ้าต้องการใช้วงเล็บแต่ถ้าต้องการแค่สร้างกลุ่มก้อนเพื่อให้มีผลในการคิดแต่ไม่ต้องการให้นับรวมอยู่ในผลลัพธ์ไปด้วยให้ใส่ ?: ไว้ขึ้นต้นคำในวงเล็บ

ตัวอย่าง
p = '(.*)((?:[ก-ฮ]า(?:ร์)?)|(?:โ[ก-ฮ]))(.+)'
print(pokemon.str.extract(p,expand=True))

ได้
  0 1 2
1 ฟุชิงิ ดา เนะ
2 ฟุชิงิ โซ
3 ฟุชิงิ บา นะ
4 ฮิโต คา เงะ
5 ลิ ซาร์ โด
6 ลิ ซาร์ ดอน
7 เซนิ งา เมะ
8   คา เมล
9   คา เม็กซ์



เมธอดบางส่วนของสายอักขระ
นอกจากที่กล่าวมาข้างต้นแล้ว เมธอดบางส่วนที่ใช้ได้กับข้อมูลชนิดสายอักขระ เช่น lower, upper, strip, lstrip, rstrip, endswith, startswith ก็สามารถใช้ในนี้ได้เช่นกัน

ตัวอย่าง
pokemon = pd.Series([
        'FuShIgIdAnE','FuShIgIsOu','FuShIgIbAnA',
        'HiToKaGe','LiZaRdO','LiZaRdOn',
        'ZeNiGaMe','KaMeIl','KaMeX'],
    index=[1,2,3,4,5,6,7,8,9])
print(pd.concat([
    pokemon,
    pokemon.str.capitalize(),
    pokemon.str.lower(),
    pokemon.str.upper()],
    axis=1))

ได้
  0 1 2 3
1 FuShIgIdAnE Fushigidane fushigidane FUSHIGIDANE
2 FuShIgIsOu Fushigisou fushigisou FUSHIGISOU
3 FuShIgIbAnA Fushigibana fushigibana FUSHIGIBANA
4 HiToKaGe Hitokage hitokage HITOKAGE
5 LiZaRdO Lizardo lizardo LIZARDO
6 LiZaRdOn Lizardon lizardon LIZARDON
7 ZeNiGaMe Zenigame zenigame ZENIGAME
8 KaMeIl Kameil kameil KAMEIL
9 KaMeX Kamex kamex KAMEX



อ้างอิง


<< บทที่แล้ว      บทถัดไป >>
หน้าสารบัญ


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> pandas

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
python
-- numpy
-- matplotlib

-- pandas
-- pytorch
maya
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
เรียนภาษาจีน
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

หลักการเขียนทับศัพท์ภาษาจีนกวางตุ้ง
การใช้ unix shell เบื้องต้น ใน linux และ mac
หลักการเขียนทับศัพท์ภาษาจีนกลาง
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
บันทึกการเที่ยวสวีเดน 1-12 พ.ค. 2014
แนะนำองค์การวิจัยและพัฒนาการสำรวจอวกาศญี่ปุ่น (JAXA)
เล่าประสบการณ์ค่ายอบรมวิชาการทางดาราศาสตร์โดยโซวเคนได 10 - 16 พ.ย. 2013
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
บันทึกการเที่ยวญี่ปุ่นครั้งแรกในชีวิต - ทุกอย่างเริ่มต้นที่สนามบินนานาชาติคันไซ
หลักการเขียนทับศัพท์ภาษาญี่ปุ่น
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ
ทำไมถึงอยากมาเรียนต่อนอก
เหตุผลอะไรที่ต้องใช้ภาษาวิบัติ?

ไทย

日本語

中文