P05-1 Read CSV#
資料來源:政府開放資料違規藥品廣告資料集
Get and open file
Get file by link then read
Read file on local machine
Mount Google Drive and read file using Colab
Read CSV
by
f.read()
by
f.readlines()
by
csv.reader()
Write CSV
by
f.write()
by
csv.writer()
Get and Open File#
如果是在Colab或JupyterLab上,可以用
wget
指令將該檔案抓回來現在的資料夾中(推薦上課中這麼做)。如果是用VSCode或jupyter撰寫,建議把csv檔下載回本機端,放到程式碼的資料夾。接下來只要弄懂資料路徑就可以讀取。https://raw.githubusercontent.com/p4css/py4css/main/data/drug_156_2.csv
如果是在colab上執行,可以先在程式中mount google drive,並把位置指到相對應的路徑。
Method 1:Colab/jupyterlab. Read file via link#
在Colab上可以用wget
指令,將該檔案讀回來,-o
的意思是代表如果已經有一樣的檔案就覆寫(Overwrite)過去,-o
後面是新的檔名,可以用此命名為比較好記的檔名,但我個人習慣保持一樣的檔名。wget
的步驟是把檔案抓回Colab的工作環境中。下一步才是開啟檔案。
# Uncomment the following code when you run on colab or jupyter-lab
# !wget https://raw.githubusercontent.com/p4css/py4css/main/data/drug_156_2.csv -O drug_156_2.csv
# with open("drug_156_2.csv", "r", encoding="utf-8-sig") as f:
# print(f)
# print(type(f))
Method 2:Jupyterlab. Read from local PC#
如果是在個人PC上,用VS Code或Jupyter等自行安裝的編輯器寫作的話,那就需要在程式碼中指定該檔案的路徑,通常以指定相對路徑為佳。相關說明如相對路徑
如果.ipynb和test.csv在同一個資料夾內,用
test.csv
或者./test.csv
便可讀取在同一個資料夾內的檔案。如果test.csv被放置在.ipynb所在位置的test資料夾中,用
test/test.csv
便可讀取,意即,在同一層中的test資料夾中的test.csv。如果test.csv被放置在.ipynb所在位置的外部資料夾中,那就要用
../test.csv
往外跳出這層資料夾,每多一個..
就代表往外跳一層,例如../../test.csv
代表往外跳兩層
# Be sure to specify right path
with open("drug_156_2.csv", "r", encoding="utf-8-sig") as f:
print(f)
print(type(f))
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[2], line 2
1 # Be sure to specify right path
----> 2 with open("drug_156_2.csv", "r", encoding="utf-8-sig") as f:
3 print(f)
4 print(type(f))
File ~/anaconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py:282, in _modified_open(file, *args, **kwargs)
275 if file in {0, 1, 2}:
276 raise ValueError(
277 f"IPython won't let you open fd={file} by default "
278 "as it is likely to crash IPython. If you know what you are doing, "
279 "you can use builtins' open."
280 )
--> 282 return io_open(file, *args, **kwargs)
FileNotFoundError: [Errno 2] No such file or directory: 'drug_156_2.csv'
Method 3:Colab. Mount drive then read#
Google Colab提供一個選項是把個人的Google Drive 掛載(Mount)到Colab的執行環境中,意味著可以用程式直接讀取個人放在Google drive裡面的資料。
# Mount google drive as data
from google.colab import drive
drive.mount('/content/drive')
#data path using google colab
gdrive_path = "/content/drive/My Drive/Colab Notebooks/PSS1092/data/14196_drug_adv.csv"
Read opened CSV#
當規劃要讀進一個CSV檔時,可以有三種做法:
f.read()
:這個函式讀取整個檔案的內容為一個字串,需要手動使用split('\n')
來將其切割成一行一行的資料。f.readlines()
:這個函式遇到換行符號\n
會自動將檔案內容分成多個行,每一行是一個字串。然後,你可以使用split(',')
將每一行的資料進一步切割成欄位。csv.reader()
:利用csv
函式庫的csv.reader()
函式,將文字資料轉換為 Python 物件,並自動切割成 List 中的元素。Pandas:另一個選擇是使用 Pandas 函式庫,它提供了更高級的功能來處理 CSV 檔案,後面的章節會介紹詳細內容。
當直接將已打開的檔案 f
印出時,實際上會顯示的是 f
這個變數的內容(為一個檔案物件如下列程式碼<_io.TextIOWrapper name='drug_156_2.csv' mode='r' encoding='utf-8-sig'>
,而非檔案內容本身。要讀取檔案內容,我們需要使用 f.readlines()
或 f.read()
函式。使用 f.readlines()
可以讓我們方便地讀取每一行的文字內容,而 f.read()
則會返回整個檔案的文字內容,我們可以後續自行處理。這兩者的選擇取決於我們需要處理的資料形式以及後續的處理需求。
with open("drug_156_2.csv", "r", encoding="utf-8-sig") as f:
print(f)
print(type(f))
<_io.TextIOWrapper name='drug_156_2.csv' mode='r' encoding='utf-8-sig'>
<class '_io.TextIOWrapper'>
Method 1: by f.read()
#
當我用f.read()
讀取純文字檔案內的內容時,整個內容會被轉為單一string。由於我加了Slicing f.read()[:400]
來取出前400個字,剛好可以看見第一列的詮釋資料、第一二三筆資料,但到了第三筆資料的一半,便超過400個字。
with open("drug_156_2.csv", "r") as f:
print(f.read()[:400])
違規產品名稱,違規廠商名稱或負責人,處分機關,處分日期,處分法條,違規情節,刊播日期,刊播媒體類別,刊播媒體,查處情形
"維他肝","豐怡生化科技股份有限公司/朱O","","03 31 2022 12:00AM","","廣告內容誇大不實","02 2 2022 12:00AM","廣播電台","噶瑪蘭廣播電台股份有限公司",""
"現貨澳洲Swisse ULTIBOOST維他命D片calcium vitamin VITAMIN D400粒 補鈣 骨頭","張O雯/張O雯","","01 21 2022 12:00AM","","廣告違規","11 30 2021 12:00AM","網路","蝦皮購物","輔導結案"
"✈日本 代購 參天製藥 處方簽點眼液","蘇O涵/蘇O涵","","01 25 2022 12:00AM","","無照藥商","08 27 2021 12:00AM
all_list = []
with open('drug_156_2.csv', "r", encoding="utf-8-sig") as f:
s = f.read()
for line in s.split("\n"):
row = line.split(",")
all_list.append(row)
# s.split("\n")[0].split(",")
Method 2: by readlines()
#
逐行讀取 CSV 檔案時,我們使用 readlines()
函式,它會自動判斷換行符號,將所有資料按行切割成一個清單中的元素。每一行都是一個字串,表示檔案中的一行資料。這是相對於使用 read()
函式的方式,後者讀取整個檔案內容為一個大字串,然後我們需要手動根據換行符號 \n
來切割成各行。
CSV 檔案的每一列都以換行符號 \n
作為換行,因此我們可以使用 readlines()
讀取每一行的資料。這個函式遇到換行符號 \n
時就會自動將資料分成多個行,每一行的資料都被存儲為字串。接著,我們可以遍歷這些行(例如,使用變數 line
),再使用逗號 ,
來切割每一行的資料,例如 line.split(",")
,這樣每一列的資料就變成了一個 List。最終,我們會得到一個兩層的 List,也就是 List of Lists,其中每個內部的 List 代表 CSV 檔案的一行資料。
all_list = []
with open('drug_156_2.csv', "r", encoding="utf-8-sig") as f:
# s = f.read()
for line in f.readlines():
# for line in f.read().split("\n"):
row = line.split(",")
all_list.append(row)
# all_list[:3]
# print(type(all_list))
# print(len(all_list))
# print(all_list[:3])
# # print the first 5 lists by for-loop
# for li in all_list[:5]:
# print(li)
# # print the length of data (the length of the outer list)
# print(len(all_list))
# # print element by index with two dimensions
# print(all_list[1][-2])
Method 3: by csv.reader()
#
csv_read()
並非預載於python runtime environment的基本函式,因此要import csv library,才可以使用該library中的csv_read()
Code Sample 1
import csv
with open("drug_156_2.csv", "r", encoding="utf-8-sig") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',') # delimiter: \t , ;
data_list = list(csv_reader)
Code Sample 2
import csv
all_list = []
with open('drug_156_2.csv', mode='r', newline='') as file: # 讀取CSV檔案
reader = csv.reader(file) # 建立CSV讀取器
next(reader, None) # 跳過標題行
for row in reader:
all_list.append(row)
print(all_list)
# Exploring data by ...
# type(all_list)
# datall_lista_list[0]
# all_list[:3]
# print(all_list[0])
# print(all_list[1])
# print(dataall_list_list[1][-2])
# print(len(all_list))
Write CSV#
by csv.writer()
<- Recommended!#
如果要將list-of-list的資料寫回CSV檔的話,可以使用csv
這個函式庫的writer.writerows()
函式,就可以直接把一個list-of-list寫回CSV檔
import csv
with open("output.csv", "w") as fout:
writer = csv.writer(fout)
writer.writerows(all_list)
Write line by line#
但如果你有一種「寫程式的浪漫」想自己操控寫回一個文字檔案的每一行每一個字的話,可以用下面的方式寫回去。
把第二層list的每一個元素用,
給黏起來,在後面再黏上一個\n
。
with open("output.csv", "w") as fout:
for row in all_list:
fout.write("%s\n" % ','.join(str(cell) for cell in row))
(Option) 字串操作的小技巧#
",".join(a-list)
是一個非常好用的字串函式,可以把一個list中的每個項目用某個符號(例如前面的,
)黏成字串。測試並觀察以下.join()
函式的操作
Code for Practice 01
blist = [3, 2, 1]
",".join(str(b) for b in blist)
[str(b) for b in blist]
Code for Practice 02
alist = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [11, 12, 13]]
",".join(str(a) for a in alist[0])
[str(cell) for cell in alist[0]]