φυβλαςのβλογ
phyblas的博客



จัดการข้อมูลด้วย pandas เบื้องต้น บทที่ ๑๐: การกำหนดดัชนีใหม่และการใช้ดัชนีหลายตัว
เขียนเมื่อ 2016/09/25 15:05
แก้ไขล่าสุด 2021/09/28 16:42
ปกติแล้วเดตาเฟรมประกอบไปด้วยข้อมูลหลายแถวหลายคอลัมน์ โดยจะมีคอลัมน์ที่อยู่ทางซ้ายสุดคือคอลัมน์ดัชนี

ดัชนีนั้นแท้จริงแล้วก็เป็นข้อมูลที่เรียงกันเป็นแถว ไม่ต่างอะไรจากคอลัมน์อื่น แต่จะต่างกันตรงที่ว่ามันมีหน้าที่พิเศษเพราะถูกใช้เพื่อเป็นตัวอ้างอิงหลักของตาราง

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

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



การเปลี่ยนคอลัมน์หนึ่งให้กลายเป็นดัชนี
เราสามารถเปลี่ยนคอลัมน์หนึ่งในเดตาเฟรมให้เป็นคอลัมน์ดัชนีได้โดยใช้เมธอด set_index แล้วใส่ชื่อคอลัมน์ที่ต้องการใช้ลงไป

ตัวอย่าง สร้างตารางข้อมูลโปเกมอน
import pandas as pd
pokemon = pd.DataFrame([
        [100,'บิริริดามะ',0.5,10.4],
        [102,'ทามะทามะ',0.4,2.5],
        [104,'คาระคาระ',0.4,6.5]],
    columns=['หมายเลข','สายพันธุ์','ส่วนสูง','น้ำหนัก'])
print(pokemon)



ได้
  หมายเลข สายพันธุ์ ส่วนสูง น้ำหนัก
0 100 บิริริดามะ 0.5 10.4
1 102 ทามะทามะ 0.4 2.5
2 104 คาระคาระ 0.4 6.5

จากนั้นลองตั้งให้คอลัมน์ "หมายเลข" เป็นดัชนี
print(pokemon.set_index('หมายเลข'))

ได้
  สายพันธุ์ ส่วนสูง น้ำหนัก
หมายเลข      
100 บิริริดามะ 0.5 10.4
102 ทามะทามะ 0.4 2.5
104 คาระคาระ 0.4 6.5

จะเห็นว่าเมื่อกำหนดให้คอลัมน์ "หมายเลข" เป็นดัชนี ดัชนีก็จะเปลี่ยนจากค่าตั้งต้น 0,1,2 กลายเป็นหมายเลขตามคอลัมน์นั้น และจะเห็นว่าที่คอลัมน์ของดัชนีตอนนี้มีคำว่า "หมายเลข" อยู่ด้วย นั่นคือดัชนีที่สร้างขึ้นจากวิธีนี้จะมีชื่อติดมาด้วย

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

คีย์เวิร์ด drop ถ้าเป็น 1 (True) จะหมายถึงว่าให้ลบคอลัมน์ที่กลายเป็นดัชนีทิ้งไป แต่ถ้าเป็น 0 (False) จะไม่ลบทิ้ง ปกติค่าตั้งต้นเป็น 1 คือลบทิ้ง ดังนั้นหากกำหนด drop=0 คอลัมน์นั้นก็จะยังอยู่

ตัวอย่าง ลองแก้ตัวอย่างข้างต้นใหม่โดยแค่เพิ่ม drop=0 ลงไป
print(pokemon.set_index('หมายเลข',drop=0))

ได้
  หมายเลข สายพันธุ์ ส่วนสูง น้ำหนัก
หมายเลข        
100 100 บิริริดามะ 0.5 10.4
102 102 ทามะทามะ 0.4 2.5
104 104 คาระคาระ 0.4 6.5

ปกติแล้วเวลาที่ใช้ set_index จะทำให้ดัชนีเดิมหายไป แต่หากไม่ต้องการให้หายไปก็ทำได้โดยใส่คีย์เวิร์ด append โดยใส่เป็น append=1 ซึ่งหมายถึงว่าต้องการเพิ่มเข้าไปแทนที่จะทับ (ถ้าไม่ใส่จะเป็นค่าตั้งต้นคือ append=0 หมายถึงทับไปเลย)

ตัวอย่าง
print(pokemon.set_index('หมายเลข',append=1))

ได้
    สายพันธุ์ ส่วนสูง น้ำหนัก
  หมายเลข      
0 100 บิริริดามะ 0.5 10.4
1 102 ทามะทามะ 0.4 2.5
2 104 คาระคาระ 0.4 6.5

คราวนี้จะเห็นว่าเลข 0,1,2 ยังอยู่ไม่ได้หายไปไหนแต่เพิ่ม 100,102,104 เข้ามาเป็นดัชนีเพิ่มอีก กลายเป็นดัชนีแบบหลายตัว (multiindex)

นอกจากนี้ยังมีอีกวิธีที่ทำให้เกิดดัชนีแบบหลายตัวได้ นั่นคือใส่ชื่อคอลัมน์เป็นลิสต์ใน set_index แทนที่จะใส่ชื่อคอลัมน์ตัวเดียว เช่น
pokemon = pokemon.set_index(['หมายเลข','สายพันธุ์'])
print(pokemon)

ได้
    ส่วนสูง น้ำหนัก
หมายเลข สายพันธุ์    
100 บิริริดามะ 0.5 10.4
102 ทามะทามะ 0.4 2.5
104 คาระคาระ 0.4 6.5



การจัดการกับข้อมูลที่มีดัชนีหลายตัว
ตารางข้อมูลที่มีดัชนีแบบหลายตัวนอกจากจะเกิดขึ้นได้ด้วยวิธีในตัวอย่างที่แล้วแล้วยังสามารถทำได้ตั้งแต่ตอนสร้างขึ้นโดยใส่คีย์เวิร์ด index ในรูปลิสต์ของลิสต์ของดัชนี

เช่น เดตาเฟรมดัชนีคู่ที่มีลักษณะเหมือนกับในตัวอย่างที่แล้วสามารถสร้างได้แบบนี้
pokemon = pd.DataFrame(
    [[0.5,10.4],[0.4,2.5],[0.4,6.5]],
    columns=['ส่วนสูง','น้ำหนัก'],
    index=[[100,102,104],['บิริริดามะ','ทามะทามะ','คาระคาระ']])
print(pokemon)

ได้
    ส่วนสูง น้ำหนัก
100 บิริริดามะ 0.5 10.4
102 ทามะทามะ 0.4 2.5
104 คาระคาระ 0.4 6.5

จะเห็นว่าต่างกันแค่ตรงที่ไม่มีชื่อของคอลัมน์ดัชนีติดมาด้วย เพราะไม่ได้มีที่มาจากคอลัมน์ แต่ก็สามารถใส่เพิ่มได้โดย
pokemon.index.names = ['หมายเลข','สายพันธุ์']

หรือตอนสร้างอาจใส่ index เป็นลิสต์ของซีรีส์ที่กำหนดชื่อไว้ แบบนี้ดัชนีที่ได้ก็จะมีชื่อ
data = [[0.5,10.4],[0.4,2.5],[0.4,6.5]]
c = ['ส่วนสูง','น้ำหนัก']
i1 = pd.Series([100,102,104],name='หมายเลข')
i2 = pd.Series(['บิริริดามะ','ทามะทามะ','คาระคาระ'],name='สายพันธุ์')
pokemon = pd.DataFrame(data,columns=c,index=[i1,i2])

การเข้าถึงข้อมูลที่มีดัชนีหลายตัวจะต้องใส่ดัชนีในรูปของทูเพิล

ตัวอย่าง ลองเข้าถึงเดตาเฟรมข้อมูลโปเกมอนที่ได้จากตัวอย่างที่แล้ว
print(pokemon.loc[(100,'บิริริดามะ')])

ได้
ส่วนสูง     0.5
น้ำหนัก    10.4
Name: (100, บิริริดามะ), dtype: float64

สามารถเข้าถึงโดยใส่แค่ดัชนีตัวแรก (ตัวซ้ายสุด) ได้เช่นกัน เพียงแต่ผลที่ได้จะออกมาเป็นเดตาเฟรมและยังมีดัชนีตัวที่สองเหลืออยู่ โดยจะกลายมาเป็นดัชนีตัวแรกแทน และตัวแรกเดิมก็หายไป
print(pokemon.loc[100])

ได้
  ส่วนสูง น้ำหนัก
สายพันธุ์    
บิริริดามะ 0.5 10.4

ซึ่งถ้าเข้าถึงค่าของดัชนีตัวนั้นอีกทีก็จะได้ค่าเหมือนกับตัวอย่างที่แล้ว
print(pokemonpokemon.loc[100].loc['บิริริดามะ'])

ถ้าหากว่ามีข้อมูลที่มีดัชนีตัวแรกเหมือนกันแต่ดัชนีตัวที่สองต่างกัน กรณีแบบนี้ก็จะให้ผลออกมามากกว่าหนึ่งตัว

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

ตัวอย่างกรณีที่เหมาะจะใช้ดัชนี ๒ ตัว เช่นลองดูข้อมูลโปเกมอนในตัวอย่างต่อไปนี้
pokemon = pd.DataFrame([
        ['มิโนมุจจิ','แมลง',40,29,45,36],
        ['มิโนมาดาม','แมลง/พืช',60,59,85,36],
        ['มิโนมาดาม','แมลง/ดิน',60,79,105,36],
        ['มิโนมาดาม','แมลง/เหล็ก',60,69,95,36],
        ['การ์เมล','แมลง/บิน',70,94,50,66],
        ['มิตสึฮันนี','แมลง/บิน',30,30,42,70],
        ['บีควีน','แมลง/บิน',70,80,102,40]],
    columns=['สายพันธุ์','ชนิด','HP','พลังโจมตี','พลังป้องกัน','ความไว'])
pokemon = pokemon.set_index('สายพันธุ์')
print(pokemon)



ได้
  ชนิด HP พลังโจมตี พลังป้องกัน ความไว
สายพันธุ์          
มิโนมุจจิ แมลง 40 29 45 36
มิโนมาดาม แมลง/พืช 60 59 85 36
มิโนมาดาม แมลง/ดิน 60 79 105 36
มิโนมาดาม แมลง/เหล็ก 60 69 95 36
การ์เมล แมลง/บิน 70 94 50 66
มิตสึฮันนี แมลง/บิน 30 30 42 70
บีควีน แมลง/บิน 70 80 102 40

จะเห็นว่าในที่นี้ใช้ "สายพันธุ์" เป็นดัชนี แต่ว่าสายพันธุ์มีการซ้ำกันอยู่ เพราะมิโนมาดามเป็นโปเกมอนที่แบ่งย่อยเป็น ๓​ ชนิด คุณสมบัติความสามารถก็ต่างกันไปหมดด้วย ดังนั้นบอกแค่สายพันธุ์ก็ไม่มีทางรู้ว่าเจาะจงถึงตัวไหน

ตอนนี้ถ้าลองใช้ดัชนีเพื่อเข้าถึงก็จะได้ผลออกมาหลายตัว
print(pokemon.loc['มิโนมาดาม'])

ได้
  ชนิด HP พลังโจมตี พลังป้องกัน ความไว
สายพันธุ์          
มิโนมาดาม แมลง/พืช 60 59 85 36
มิโนมาดาม แมลง/ดิน 60 79 105 36
มิโนมาดาม แมลง/เหล็ก 60 69 95 36

แต่หากลองเพิ่มดัชนีเข้าไปอีกตัว โดยกำหนดให้ "ชนิด" เป็นดัชนีด้วย
pokemon = pokemon.set_index('ชนิด',append=1)
print(pokemon)

ได้
    HP พลังโจมตี พลังป้องกัน ความไว
สายพันธุ์ ชนิด        
มิโนมุจจิ แมลง 40 29 45 36
มิโนมาดาม แมลง/พืช 60 59 85 36
แมลง/ดิน 60 79 105 36
แมลง/เหล็ก 60 69 95 36
การ์เมล แมลง/บิน 70 94 50 66
มิตสึฮันนี แมลง/บิน 30 30 42 70
บีควีน แมลง/บิน 70 80 102 40

จะเห็นว่ามิโนมาดามทั้ง ๓ ถูกรวมอยู่เป็นกลุ่มเดียวให้เห็นชัด

เวลาที่เข้าถึงก็ใส่ดัชนีทั้งสองตัว
print(pokemon.loc['มิโนมาดาม','แมลง/ดิน'])
# หรือ pokemon.loc['มิโนมาดาม'].loc['แมลง/ดิน']

ได้
HP              60
พลังโจมตี       79
พลังป้องกัน    105
ความไว          36
Name: (มิโนมาดาม, แมลง/ดิน), dtype: int64

การรวมกลุ่มจะเริ่มรวมจากดัชนีตัวแรกสุดก่อน โดยจะรวมเมื่อตัวที่อยู่ติดกันมีดัชนีตัวแรกเหมือนกัน แต่ดัชนีตัวถัดมาต่อให้เหมือนกันก็จะไม่มีการรวมกลุ่มกัน

ตรงนี้จะเห็นได้ถึงความสำคัญของลำดับของดัชนี โดยที่ตัวแรกจะสำคัญที่สุด

ความยากง่ายในการเข้าถึงก็ต่างกันด้วย คือหากเราพิมพ์ pokemon.loc['มิโนมาดาม'] ก็จะได้แถวที่มีดัชนีตัวแรกเป็นมิโนมาดามทั้งหมด แต่ถ้าต้องการแถวที่มีดัชนีตัวที่ ๒ เป็นแมลง/บิน จะพิมพ์ pokemon.loc['แมลง/บิน'] แบบนี้ไม่ได้

จะทำได้ต้องใช้เมธอด xs โดยใส่อาร์กิวเมนต์เป็นค่าดัชนีที่ต้องการ และใส่คีย์เวิร์ด level เป็นชื่อหรือลำดับของดัชนีนั้น เช่น
print(pokemon.xs('แมลง/บิน',level='ชนิด'))
# หรือ print(pokemon.xs('แมลง/บิน',level=1))

ได้
  HP พลังโจมตี พลังป้องกัน ความไว
สายพันธุ์        
การ์เมล 70 94 50 66
มิตสึฮันนี 30 30 42 70
บีควีน 70 80 102 40

และเราอาจสามารถสลับลำดับของดัชนีได้โดยใช้เมธอด swaplevel หากลองสลับดู
pokemon = pokemon.swaplevel()
print(pokemon)

ได้
    HP พลังโจมตี พลังป้องกัน ความไว
ชนิด สายพันธุ์        
แมลง มิโนมุจจิ 40 29 45 36
แมลง/พืช มิโนมาดาม 60 59 85 36
แมลง/ดิน มิโนมาดาม 60 79 105 36
แมลง/เหล็ก มิโนมาดาม 60 69 95 36
แมลง/บิน การ์เมล 70 94 50 66
มิตสึฮันนี 30 30 42 70
บีควีน 70 80 102 40

swaplevel นั้นกรณีที่มีดัชนีมากกว่า ๒ จำเป็นต้องระบุชื่อหรือลำดับของดัชนี กรณีที่มีแค่ ๒ จะระบุหรือไม่ก็ได้ ถ้าระบุก็เขียนเป็น
pokemon = pokemon.swaplevel('สายพันธุ์','ชนิด')
# หรือ pokemon = pokemon.swaplevel(0,1)

พอสลับเอา "ชนิด" มาไว้เป็นดัชนีอันแรกแล้วทีนี้ก็คัดเอาโปเกมอนที่เป็นชนิด "แมลง/บิน" ได้ง่ายๆแล้ว
print(pokemon.loc['แมลง/บิน'])

ผลที่ได้คราวนี้ก็จะเหมือนกับที่ใช้ xs ในตัวอย่างก่อนหน้า



การคืนดัชนีกลับเป็นคอลัมน์ทั่วไป
คำสั่งที่ตรงกันข้ามกับ set_index ก็คือ reset_index นั่นก็คือการปลดดัชนีออก

ตัวอย่าง
pokemon = pd.DataFrame([
        ['โคยคิง','น้ำ',20,10,55,80],
        ['เกียราดอส','น้ำ,บิน',95,125,79,81],
        ['ฮินบาส','น้ำ',20,15,20,80],
        ['มิโลคารอส','น้ำ',95,60,79,81]],
    columns=['สายพันธุ์','ชนิด','HP','พลังโจมตี','พลังป้องกัน','ความไว'],
    index=[129,130,349,350])
print(pokemon)
print(pokemon.reset_index())



ได้
  สายพันธุ์ ชนิด HP พลังโจมตี พลังป้องกัน ความไว
129 โคยคิง น้ำ 20 10 55 80
130 เกียราดอส น้ำ,บิน 95 125 79 81
349 ฮินบาส น้ำ 20 15 20 80
350 มิโลคารอส น้ำ 95 60 79 81

  index สายพันธุ์ ชนิด HP พลังโจมตี พลังป้องกัน ความไว
0 129 โคยคิง น้ำ 20 10 55 80
1 130 เกียราดอส น้ำ,บิน 95 125 79 81
2 349 ฮินบาส น้ำ 20 15 20 80
3 350 มิโลคารอส น้ำ 95 60 79 81

ดัชนีจะถูกปลดออก กลายมาเป็นแค่คอลัมน์อันหนึ่ง โดยจะเป็นคอลัมน์อันแรกสุดไป และดัชนีก็กลับมาเป็นตัวเลขเรียงจาก 0

ถ้าดัชนีไม่ได้ถูกกำหนดชื่อไว้พอมันกลายมาเป็นคอลัมน์ก็จะได้ชื่อว่า index ถ้าจะเปลี่ยนชื่อก็ค่อยไปแก้อีกทีได้

ถ้าต้องการจะทิ้งดัชนีนั้นไปเลยไม่ต้องมาเป็นคอลัมน์หนึ่งแล้วก็ทำได้โดยใส่คีย์เวิร์ด drop=1
print(pokemon.reset_index(drop=1))

ได้
  สายพันธุ์ ชนิด HP พลังโจมตี พลังป้องกัน ความไว
0 โคยคิง น้ำ 20 10 55 80
1 เกียราดอส น้ำ,บิน 95 125 79 81
2 ฮินบาส น้ำ 20 15 20 80
3 มิโลคารอส น้ำ 95 60 79 81

กรณีที่เป็นดัชนีแบบหลายตัวดัชนีทุกตัวจะถูกปลดทั้งหมดและถูกตั้งชื่อให้ใหม่เองถ้าไม่มีชื่ออยู่ก่อน
pokemon = pd.DataFrame([
        [50,53,48,64],
        [75,98,63,101],
        [50,53,48,64],
        [75,98,63,101],
        [50,53,48,64],
        [75,98,63,101]],
    columns=['HP','พลังโจมตี','พลังป้องกัน','ความไว'],
    index=[['พืช','พืช','ไฟ','ไฟ','น้ำ','น้ำ'],
           ['ยานัปปุ','ยานักกี','บาอ็อปปุ','บาอ็อกกี','ฮิยัปปุ','ฮิยักกี']])
print(pokemon)
print(pokemon.reset_index())



ได้
    HP พลังโจมตี พลังป้องกัน ความไว
พืช ยานัปปุ 50 53 48 64
ยานักกี 75 98 63 101
ไฟ บาอ็อปปุ 50 53 48 64
บาอ็อกกี 75 98 63 101
น้ำ ฮิยัปปุ 50 53 48 64
ฮิยักกี 75 98 63 101

  level_0 level_1 HP พลังโจมตี พลังป้องกัน ความไว
0 พืช ยานัปปุ 50 53 48 64
1 พืช ยานักกี 75 98 63 101
2 ไฟ บาอ็อปปุ 50 53 48 64
3 ไฟ บาอ็อกกี 75 98 63 101
4 น้ำ ฮิยัปปุ 50 53 48 64
5 น้ำ ฮิยักกี 75 98 63 101

แต่หากต้องการให้ปลดเฉพาะบางตัวก็สามารถทำได้โดยใส่ลำดับของดัชนีที่ต้องการปลด เช่นจะเอาตัวแรกออกก็ใส่ 0
print(pokemon.reset_index(0))

ได้
  level_0 HP พลังโจมตี พลังป้องกัน ความไว
ยานัปปุ พืช 50 53 48 64
ยานักกี พืช 75 98 63 101
บาอ็อปปุ ไฟ 50 53 48 64
บาอ็อกกี ไฟ 75 98 63 101
ฮิยัปปุ น้ำ 50 53 48 64
ฮิยักกี น้ำ 75 98 63 101

เมธอด reset_index สามารถใช้กับซีรีส์ได้ด้วย โดยจะได้ผลเป็นเดตาเฟรม เช่น
pokemon = pd.Series(['ซันนีโก','เทปโปวโอ','โอกุแท็งก์'],index=[222,223,224])
# 222       ซันนีโก
# 223      เทปโปวโอ
# 224    โอกุแท็งก์

print(pokemon.reset_index())



ได้
  index 0
0 222 ซันนีโก
1 223 เทปโปวโอ
2 224 โอกุแท็งก์

แต่ถ้าใส่คีย์เวิร์ด drop=1 (หมายถึงให้ทิ้งดัชนีเดิมไปเลยไม่ต้องเก็บไว้) ก็จะได้ซีรีส์เหมือนเดิม แค่ดัชนีถูกปลดเหลือ 0,1,2 ไปเท่านั้น
print(pokemon.reset_index(drop=1))

ได้
0       ซันนีโก
1      เทปโปวโอ
2    โอกุแท็งก์
dtype: object



อ้างอิง


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


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

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

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

หมวดหมู่

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

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

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ