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



จัดการข้อมูลด้วย pandas เบื้องต้น บทที่ ๑๘: การจัดการกับ json
เขียนเมื่อ 2019/07/21 23:30
แก้ไขล่าสุด 2021/09/28 16:42
json เป็นรูปแบบการจัดเก็บข้อมูลแบบหนึ่งที่นิยมใช้ในภาษา javascript

เกี่ยวกับการจัดการกับ json ภายในภาษาไพธอนได้อธิบายในนี้ไว้แล้ว https://phyblas.hinaboshi.com/20190427

สำหรับในหน้านี้จะพูดถึงการใช้ pandas ในการจัดการกับ json

pandas มีคำสั่งที่ใช้อ่านและเขียน json ซึ่งสะดวกมาก ใช้งานได้ง่าย

สำหรับการอ่าน json มาเป็นเดตาเฟรมให้ใช้ pd.read_json และในทางกลับกันเมื่อจะเปลี่ยนเดตาเฟรมเป็น json ให้ใช้เมธอด to_json ที่ตัวเดตาเฟรมนั้น



อ่านไฟล์ json ด้วยฟังก์ชัน pd.read_json

ฟังก์ชัน pd.read_json สามารถอ่าน json จากไฟล์โดยตรง หรือจากสายอักขระข้อความที่เป็น json ก็ได้

ปกติถ้าใส่ชื่อไฟล์ในคำสั่ง pd.read_json จะเป็นการอ่าน json จากไฟล์ตามชื่อนั้น แต่ถ้าใส่ข้อความที่เขียนเป็น json ลงไปก็จะเป็นการแปลงข้อความ json นั้นเป็นเดตาเฟรม

เช่นถ้ามีไฟล์ json อยู่ก็ใส่ชื่อไฟล์ลงไป ก็จะเป็นการอ่าน json จากไฟล์นั้น
df = pd.read_json('pokemon.json')

นอกจากนี้ยังสามารถอ่าน json จากไฟล์ที่อยู่ในรูปที่ถูกบีบอัดอยู่ได้ด้วย

เช่นอ่านไฟล์บีบอัด gzip (.gz)
df = pd.read_json('pokemon.json.gz')

ไฟล์ที่ใส่เข้าไปจะเป็นไฟล์ json เปล่าๆหรือเป็น โปรแกรมจะตัดสินเอาจากสกุลไฟล์ แต่จะใส่ตัวเลือก compression เพื่อระบุชัดก็ได้

df = pd.read_json('pokemon.json.gz',compression='gzip')

ไฟล์บีบอัดชนิดต่างๆที่ใช้ได้คือ 'bz2', 'gzip', 'xz', 'zip'



อ่าน json จากสายอักขระ

หากมีสายอักขระที่เขียนข้อมูลในรูปแบบ json อยู่ ก็สามารถใช้ pd.read_json อ่านขึ้นมาได้

json ที่ป้อนเข้าไปจะอยู่ในรูปแบบออบเจ็กต์หรืออาเรย์ก็ได้ แต่จำเป็นต้องซ้อนสองชั้น ถ้าเป็นอาเรย์ก็จะไม่มีชื่อคอลัมน์และดัชนี ก็จะกลายเป็น 0,1,2,...

ตัวอย่าง
import pandas as pd

# ออบเจ็กต์ของออบเจ็กต์
js = '{"สายพันธุ์":{"1": "ฟุชิงิดาเนะ","2": "ฟุชิงิโซว"},"หนัก":{"1":6.9, "2": 13}}'
df = pd.read_json(js)
print(df)

# ออบเจ็กต์ของอาเรย์
js = '{"สายพันธุ์":["ฟุชิงิดาเนะ","ฟุชิงิโซว"],"หนัก":[6.9,13]}'
df = pd.read_json(js)
print(df)

# อาเรย์ของอาเรย์
js = '[["ฟุชิงิดาเนะ",6.9],["ฟุชิงิโซว",13]]'
df = pd.read_json(js)
print(df)

# อาเรย์ของออบเจ็กต์
js = '[{"สายพันธุ์": "ฟุชิงิดาเนะ","หนัก": 6.9},{"สายพันธุ์":"ฟุชิงิโซว", "หนัก": 13}]'
df = pd.read_json(js)
print(df)

ได้
  สายพันธุ์ หนัก
1 ฟุชิงิดาเนะ 6.9
2 ฟุชิงิโซว 13.0

  สายพันธุ์ หนัก
0 ฟุชิงิดาเนะ 6.9
1 ฟุชิงิโซว 13.0

  0 1
0 ฟุชิงิดาเนะ 6.9
1 ฟุชิงิโซว 13.0

  สายพันธุ์ หนัก
0 ฟุชิงิดาเนะ 6.9
1 ฟุชิงิโซว 13.0

ถ้าข้อมูลออบเจ็กต์มีแค่บางส่วน ส่วนที่ขาดก็จะกลายเป็น NaN
js = '[{"สายพันธุ์": "ฟุชิงิดาเนะ","หนัก": 6.9},{"สายพันธุ์":"ฟุชิงิโซว", "สูง": 1}]'
df = pd.read_json(js)
print(df)

ได้
  สายพันธุ์ สูง หนัก
0 ฟุชิงิดาเนะ NaN 6.9
1 ฟุชิงิโซว 1.0 NaN


อ่าน json เป็นซีรีส์

ปกติคำสั่ง pd.read_json จะอ่าน json ออกมาเป็นเดตาเฟรม แต่ถ้าหากแค่ต้องการอ่านเป็นซีรีส์ก็ทำได้โดยใส่ตัวเลือก typ='series'

กรณีที่เป็นซีรีส์แบบนี้ข้อมูลที่ใส่ก็คือ json ของอาเรย์หรือออบเจ็กต์ชั้นเดียว

เช่น
# อาเรย์
js = '["ฟุชิงิดาเนะ","ฟุชิงิโซว"]'
sr = pd.read_json(js,typ='series')
print(sr)

# ออบเจ็กต์
js = '{"1": "ฟุชิงิดาเนะ","2": "ฟุชิงิโซว"}'
sr = pd.read_json(js,typ='series')
print(sr)

ได้
0    ฟุชิงิดาเนะ
1      ฟุชิงิโซว
dtype: object

1    ฟุชิงิดาเนะ
2      ฟุชิงิโซว
dtype: object



เขียนเดตาเฟรมเป็น json ด้วยเมธอด to_json

เดตาเฟรมมีเมธอด to_json ใช้สำหรับแปลงเป็น json
df = pd.DataFrame([
        ['fushigidane',0.7,6.9],
        ['hitokage',0.6,8.5],
        ['zenigame',0.5,9.0]])
print(df)
print(df.to_json())

ได้

  0 1 2
0 fushigidane 0.7 6.9
1 hitokage 0.6 8.5
2 zenigame 0.5 9.0
{"0":{"0":"fushigidane","1":"hitokage","2":"zenigame"},"1":{"0":0.7,"1":0.6,"2":0.5},"2":{"0":6.9,"1":8.5,"2":9.0}}

หากใส่ชื่อไฟล์ลงไปจะเป็นการเขียนบันทึกลงไฟล์

df.to_json('pokemon.json')

สามารถใส่ตัวเลือกเสริม compression ได้หากต้องการให้มีการบีบอัดไฟล์ โดยใส่ชนิดไฟล์ที่ต้องการ ซึ่งอาจเป็น 'gzip', 'bz2', 'zip', 'xz'

df.to_json('pokemon.json.gz',compression='gzip')

เวลาที่แปลงเป็น json โดยปกติแล้วถ้ามีอักษรที่ไม่ใช่ ascii เช่นตัวอักษรภาษาไทยก็จะถูกเปลี่ยนเป็นรหัส

เช่น
df = pd.DataFrame([
        ['ฟุชิงิดาเนะ','พืช/พิษ',0.7,6.9],
        ['ฟุชิงิโซว','พืช/พิษ',1.0,13.0],
        ['ฟุชิงิบานะ','พืช/พิษ',2.4,155.5]
    ],
    columns=['สายพันธุ์','ชนิด','ส่วนสูง','น้ำหนัก'],
    index=[1,2,3]
)
print(df)
print(df.to_json())

ได้

  สายพันธุ์ ชนิด ส่วนสูง น้ำหนัก
1 ฟุชิงิดาเนะ พืช/พิษ 0.7 6.9
2 ฟุชิงิโซว พืช/พิษ 1.0 13.0
3 ฟุชิงิบานะ พืช/พิษ 2.4 155.5
{"\u0e2a\u0e32\u0e22\u0e1e\u0e31\u0e19\u0e18\u0e38\u0e4c":{"1":"\u0e1f\u0e38\u0e0a\u0e34\u0e07\u0e34\u0e14\u0e32\u0e40\u0e19\u0e30","2":"\u0e1f\u0e38\u0e0a\u0e34\u0e07\u0e34\u0e42\u0e0b\u0e27","3":"\u0e1f\u0e38\u0e0a\u0e34\u0e07\u0e34\u0e1a\u0e32\u0e19\u0e30"},"\u0e0a\u0e19\u0e34\u0e14":{"1":"\u0e1e\u0e37\u0e0a\/\u0e1e\u0e34\u0e29","2":"\u0e1e\u0e37\u0e0a\/\u0e1e\u0e34\u0e29","3":"\u0e1e\u0e37\u0e0a\/\u0e1e\u0e34\u0e29"},"\u0e2a\u0e48\u0e27\u0e19\u0e2a\u0e39\u0e07":{"1":0.7,"2":1.0,"3":2.4},"\u0e19\u0e49\u0e33\u0e2b\u0e19\u0e31\u0e01":{"1":6.9,"2":13.0,"3":155.5}}

เพื่อที่จะให้ยังคงเป็นอักษรตามเดิม ให้ใส่ตัวเลือก force_ascii=False เข้าไป

print(df.to_json(force_ascii=0))

ได้

{"สายพันธุ์":{"1":"ฟุชิงิดาเนะ","2":"ฟุชิงิโซว","3":"ฟุชิงิบานะ"},"ชนิด":{"1":"พืช\/พิษ","2":"พืช\/พิษ","3":"พืช\/พิษ"},"ส่วนสูง":{"1":0.7,"2":1.0,"3":2.4},"น้ำหนัก":{"1":6.9,"2":13.0,"3":155.5}}

ตำแหน่งทศนิยมสำหรับข้อมูลที่เป็นทศนิยม หากไม่ได้กำหนดจะมี ๑๐ ตัว หากต้องการกำหนดเองสามารถใส่ double_precision
df = pd.DataFrame([1/3.])
print(df.to_json()) # ได้ {"0":{"0":0.3333333333}}
print(df.to_json(double_precision=3)) # ได้ {"0":{"0":0.333}}


ตัวเลือก orient

รูปแบบในการเขียน json นั้นจริงๆแล้วทำได้หลายแบบ โดยรูปแบบตั้งต้นคือการแบ่งตามคอลัมน์ แล้วระบุค่าแต่ละแถวในคอลัมน์

หากต้องการเปลี่ยนรูปแบบการเขียนสามารถทำได้โดยใช้ตัวเลือก orient

หากไม่ใส่ตัวเลือก orient จะเป็นค่าตั้งต้น คือ 'columns' คือแบ่งตามคอลัมส์ก่อน

แต่หากใส่ orient='index' จะแบ่งตามแถวก่อน

ตัวอย่างเปรียบเทียบ

df = pd.DataFrame([
        ['ฟุชิงิดาเนะ',0.7,6.9],
        ['ฮิโตคาเงะ',0.6,8.5],
        ['เซนิงาเมะ',0.5,9.0]
    ],
    columns=['สายพันธุ์','ส่วนสูง','น้ำหนัก'],
    index=[1,4,7]
)

print(df.to_json(orient='columns',force_ascii=0))
print(df.to_json(orient='index',force_ascii=0))

ได้
{"สายพันธุ์":{"1":"ฟุชิงิดาเนะ","4":"ฮิโตคาเงะ","7":"เซนิงาเมะ"},"ส่วนสูง":{"1":0.7,"4":0.6,"7":0.5},"น้ำหนัก":{"1":6.9,"4":8.5,"7":9.0}}
{"1":{"สายพันธุ์":"ฟุชิงิดาเนะ","ส่วนสูง":0.7,"น้ำหนัก":6.9},"4":{"สายพันธุ์":"ฮิโตคาเงะ","ส่วนสูง":0.6,"น้ำหนัก":8.5},"7":{"สายพันธุ์":"เซนิงาเมะ","ส่วนสูง":0.5,"น้ำหนัก":9.0}}

ถ้า orient='records' จะแยกตามแถว คล้าย orient='index' เพียงแต่ดัชนีแถวจะถูกละทิ้งไป
print(df.to_json(orient='records',force_ascii=0))

ได้
[{"สายพันธุ์":"ฟุชิงิดาเนะ","ส่วนสูง":0.7,"น้ำหนัก":6.9},{"สายพันธุ์":"ฮิโตคาเงะ","ส่วนสูง":0.6,"น้ำหนัก":8.5},{"สายพันธุ์":"เซนิงาเมะ","ส่วนสูง":0.5,"น้ำหนัก":9.0}]

เมื่อใช้ orient='records' หากใส่ตัวเลือก lines=True จะทำให้แบ่งเป็นบรรทัดแทน แทนที่จะกั้นด้วยจุลภาค ,

print(df.to_json(orient='records',lines=1,force_ascii=0))

ได้
{"สายพันธุ์":"ฟุชิงิดาเนะ","ส่วนสูง":0.7,"น้ำหนัก":6.9}
{"สายพันธุ์":"ฮิโตคาเงะ","ส่วนสูง":0.6,"น้ำหนัก":8.5}
{"สายพันธุ์":"เซนิงาเมะ","ส่วนสูง":0.5,"น้ำหนัก":9.0}

ถ้า orient='values' ทั้งชื่อคอลัมน์และชื่อแถวจะถูกละทิ้งทั้งหมด

print(df.to_json(orient='values',force_ascii=0))

ได้
[["ฟุชิงิดาเนะ",0.7,6.9],["ฮิโตคาเงะ",0.6,8.5],["เซนิงาเมะ",0.5,9.0]]

หาก orients='split' ชื่อคอลัมน์และชื่อแถวจะถูกแยกออกมาเก็บไว้ต่างหาก ส่วนข้อมูลก็จะบันทึกเหมือนกับเมื่อใช้ orient='values'
print(df.to_json(orient='split',force_ascii=0))

ได้
{"columns":["สายพันธุ์","ส่วนสูง","น้ำหนัก"],"index":[1,4,7],"data":[["ฟุชิงิดาเนะ",0.7,6.9],["ฮิโตคาเงะ",0.6,8.5],["เซนิงาเมะ",0.5,9.0]]}

ถ้า orient='table' จะเป็นตารางแบบที่บันทึกข้อมูลใน sql มีระบุชนิดข้อมูลไว้ชัดเจนด้วย

ในส่วนข้อมูลจะแยกตามแถว คล้าย orient='index'

เพียงแต่ว่าชื่อคอลัมน์ในส่วนของ fields จะถูกแปลงเป็นโค้ด แม้ว่าจะกำหนด force_ascii=0 ก็ตาม

print(df.to_json(orient='table',force_ascii=0))

ได้
{"schema":   {"fields":[{"name":"index","type":"integer"},{"name":"\u0e2a\u0e32\u0e22\u0e1e\u0e31\u0e19\u0e18\u0e38\u0e4c","type":"string"},{"name":"\u0e2a\u0e48\u0e27\u0e19\u0e2a\u0e39\u0e07","type":"number"},{"name":"\u0e19\u0e49\u0e33\u0e2b\u0e19\u0e31\u0e01","type":"number"}],"primaryKey":["index"],"pandas_version":"0.20.0"},  "data":  [{"index":1,"สายพันธุ์":"ฟุชิงิดาเนะ","ส่วนสูง":0.7,"น้ำหนัก":6.9},{"index":4,"สายพันธุ์":"ฮิโตคาเงะ","ส่วนสูง":0.6,"น้ำหนัก":8.5},{"index":7,"สายพันธุ์":"เซนิงาเมะ","ส่วนสูง":0.5,"น้ำหนัก":9.0}]}

เวลาที่ใช้ pd.read_json เพื่ออ่านข้อมูลที่บันทึกด้วยตัวเลือก orient แบบนี้ จะต้องกำหนด orient ตามให้ตรงด้วย
js = '{"columns":["ชื่อ"],"index":[25,26],"data":[["พีคาชู"],["ไรชู"]]}'
print(pd.read_json(js,orient='split'))

ได้

  ชื่อ
25 พีคาชู
26 ไรชู



การใช้ json_normalize

มีฟังก์ชันหนึ่งที่เกียวข้องกับ json ซึ่งค่อนข้างเข้าใจยากสักหน่อย แต่มีประโยชน์ นั่นคือ json_normalize

สมมุติว่ามีข้อมูล json ที่มีการซ้อนกันซับซ้อนหน่อย เช่นแบบนี้

jdata1.json
[
  {
    "เลข": 152,
    "ชื่อ": {
      "ไทย": "ชิโครีตา",
      "ญี่ปุ่น": "チコリータ"
    }
  },
  {
    "เลข": 155,
    "ชื่อ": {
      "ไทย": "ฮิโนอาราชิ",
      "ญี่ปุ่น": "ヒノアラシ"
    }
  },
  {
    "เลข": 158,
    "ชื่อ": {
      "ไทย": "วานิโนโกะ",
      "ญี่ปุ่น": "ワニノコ"
    }
  }
]

ถ้าหากนำมาแปลงเป็นเดตาเฟรมด้วยวิธีปกติก็จะพบว่าดิกชันนารีด้านในอยู่รวมตาราง
print(pd.read_json('jdata1.json'))

ได้

  ชื่อ เลข
0 {'ไทย': 'ชิโครีตา', 'ญี่ปุ่น': 'チコリータ'} 152
1 {'ไทย': 'ฮิโนอาราชิ', 'ญี่ปุ่น': 'ヒノアラシ'} 155
2 {'ไทย': 'วานิโนโกะ', 'ญี่ปุ่น': 'ワニノコ'} 158

แต่หากเริ่มอ่านมาเป็นดิกชันนารีก่อนแล้วใช้ json_normalize เพื่อแปลง โครงสร้างภายในจะถูกอ่านแล้วได้ชื่อคอลัมน์ซ้อนเข้าไป
import json
from pandas.io.json import json_normalize

with open('jdata1.json') as f:
    jdata = json.load(f)

print(json_normalize(jdata))

ได้

  ชื่อ.ญี่ปุ่น ชื่อ.ไทย เลข
0 チコリータ ชิโครีตา 152
1 ヒノアラシ ฮิโนอาราชิ 155
2 ワニノコ วานิโนโกะ 158

โครงสร้างซ้อน ๓ ชั้นแบบนี้ก็สามารถอ่านได้

jdata2.json
[
  {
    "เลข": 152,
    "ข้อมูล": {
      "ชื่อ": {
        "ไทย": "ชิโครีตา",
        "ญี่ปุ่น": "チコリータ"
      },
      "ส่วนสูง": 0.9,
      "น้ำหนัก": 6.4
    }
  },
  {
    "เลข": 155,
    "ข้อมูล": {
      "ชื่อ": {
        "ไทย": "ฮิโนอาราชิ",
        "ญี่ปุ่น": "ヒノアラシ"
      },
      "ส่วนสูง": 0.5
    }
  },
  {
    "เลข": 158,
    "ข้อมูล": {
      "ชื่อ": {
        "ไทย": "วานิโนโกะ",
        "ญี่ปุ่น": "ワニノコ"
      },
      "น้ำหนัก": 9.5
    }
  }
]

with open('jdata2.json') as f:
    jdata = json.load(f)

print(json_normalize(jdata))

ได้

  ข้อมูล.ชื่อ.ญี่ปุ่น ข้อมูล.ชื่อ.ไทย ข้อมูล.น้ำหนัก ข้อมูล.ส่วนสูง เลข
0 チコリータ ชิโครีตา 6.4 0.9 152
1 ヒノアラシ ฮิโนอาราชิ NaN 0.5 155
2 ワニノコ วานิโนโกะ 9.5 NaN 158

ต่อมาลองดูข้อมูลที่ซับซ้อนขึ้นไปอีก แบบนี้

jdata3.json
[
  {
    "เทรนเนอร์": "โกลด์",
    "โปเกมอน": [
      {
        "เลข": 152,
        "ชื่อ": "ชิโครีตา"
      },
      {
        "เลข": 161,
        "ชื่อ": "โอตาจิ"
      },
      {
        "เลข": 167,
        "ชื่อ": "อิโตมารุ"
      }
    ]
  },
  {
    "เทรนเนอร์": "ซิลเวอร์",
    "โปเกมอน": [
      {
        "เลข": 155,
        "ชื่อ": "ฮิโนอาราชิ"
      },
      {
        "เลข": 163,
        "ชื่อ": "โฮโฮ"
      }
    ]
  },
  {
    "เทรนเนอร์": "คริสตัล",
    "โปเกมอน": [
      {
        "เลข": 158,
        "ชื่อ": "วานิโนโกะ"
      },
      {
        "เลข": 165,
        "ชื่อ": "เรดีบา"
      }
    ]
  }
]

ในที่นี้มีข้อมูล ๓ กลุ่มของเทรนเนอร์ ๓ คน โดย "เทรนเนอร์" คือชื่อของเทรนเนอร์ ส่วน "โปเกมอน" บอกข้อมูลโปเกมอนที่มี

กรณีนี้ก็สามารถใช้ json_normalize เพื่ออ่านได้ แต่ต้องระบุชื่อคีย์สำหรับข้อมูลในแต่ละกลุ่ม ในที่นี้คือ "โปเกมอน" และระบุค่าอื่นๆที่จะใส่ด้วย ในที่นี้คือ "เทรนเนอร์"
with open('jdata3.json') as f:
    jdata = json.load(f)

df = json_normalize(jdata,'โปเกมอน','เทรนเนอร์')
print(df)

ได้

  ชื่อ เลข เทรนเนอร์
0 ชิโครีตา 152 โกลด์
1 โอตาจิ 161 โกลด์
2 อิโตมารุ 167 โกลด์
3 ฮิโนอาราชิ 155 ซิลเวอร์
4 โฮโฮ 163 ซิลเวอร์
5 วานิโนโกะ 158 คริสตัล
6 เรดีบา 165 คริสตัล


ส่วนการสร้างข้อมูล json ในลักษณะนี้จากเดตาเฟรมอาจทำได้โดยวิธีการในลักษณะนี้
lis = []
for tr,p in df.groupby('เทรนเนอร์'):
    pokemon = []
    for _,pk in p.iterrows():
        pokemon.append({'เลข':pk['เลข'],'ชื่อ':pk['ชื่อ']})
    lis.append({"เทรนเนอร์":tr,"โปเกมอน":pokemon})
with open('jdata4.json','w') as f:
    json.dump(lis,f,indent=2,ensure_ascii=0)

groupby จะช่วยแบ่งกลุ่มให้ตามเทรนเนอร์ แล้วเราจะได้ชื่อเทรนเนอร์และโปเกมอนที่เป็นของเทรนเนอร์นั้น เอามาแยกสร้างดิกชันนารี แล้วสุดท้ายก็แปลงเป็น json

หรืออาจย่อเหลือในบรรทัดเดียวได้แบบนี้
with open('jdata4.json','w') as f:
     json.dump([{"เทรนเนอร์":tr,"โปเกมอน":[{c:pk[c] for c in ['เลข','ชื่อ']}  for _,pk in p.iterrows()]} for tr,p in  df.groupby('เทรนเนอร์')],f,indent=2,ensure_ascii=0)

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



อ้างอิง


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

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

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

หมวดหมู่

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

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

目录

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

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

按类别分日志



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

  查看日志

  推荐日志

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