分類類型可以通過指定 dtype='category' 或 dtype=CategoricalDtype(categories, ordered) 直接解析
In [31]: data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3"
In [32]: pd.read_csv(StringIO(data))
Out[32]:
col1 col2 col3
0 a b 1
1 a b 2
2 c d 3
In [33]: pd.read_csv(StringIO(data)).dtypes
Out[33]:
col1 object
col2 object
col3 int64
dtype: object
In [34]: pd.read_csv(StringIO(data), dtype="category").dtypes
Out[34]:
col1 category
col2 category
col3 category
dtype: object也可以使用字典對指定列設置類型
In [35]: pd.read_csv(StringIO(data), dtype={"col1": "category"}).dtypes
Out[35]:
col1 category
col2 object
col3 int64
dtype: object指定 dtype ='category' 將導致無序分類,其類別是數據中所有觀察值的集合。
如果要更好地控制類別和順序,請提前創建 CategoricalDtype,然後將其傳遞給該列的 dtype
In [36]: from pandas.api.types import CategoricalDtype
In [37]: dtype = CategoricalDtype(["d", "c", "b", "a"], ordered=True)
In [38]: pd.read_csv(StringIO(data), dtype={"col1": dtype}).dtypes
Out[38]:
col1 category
col2 object
col3 int64
dtype: object使用 dtype=CategoricalDtype 時,超出的數據類型將被視為缺失值
In [39]: dtype = CategoricalDtype(["a", "b", "d"]) # No 'c'
In [40]: pd.read_csv(StringIO(data), dtype={"col1": dtype}).col1
Out[40]:
0 a
1 a
2 NaN
Name: col1, dtype: category
Categories (3, object): ['a', 'b', 'd']這與 Categorical.set_categories() 的行為相匹配
❝注意
當 dtype='category' 時,生成的類別將始終解析為字符串(object 類型)。
如果類別是數字型,則可以使用 to_numeric() 函數或其他轉換器進行轉換,如 to_datetime()當 dtype 是一個同構(所有數字、所有日期時間等)的 CategoricalDtype 時,轉換將自動完成
In [41]: df = pd.read_csv(StringIO(data), dtype="category")
❞4 列的命名和使用4.1 處理列名
In [42]: df.dtypes
Out[42]:
col1 category
col2 category
col3 category
dtype: object
In [43]: df["col3"]
Out[43]:
0 1
1 2
2 3
Name: col3, dtype: category
Categories (3, object): ['1', '2', '3']
In [44]: df["col3"].cat.categories = pd.to_numeric(df["col3"].cat.categories)
In [45]: df["col3"]
Out[45]:
0 1
1 2
2 3
Name: col3, dtype: category
Categories (3, int64): [1, 2, 3]一個文件可能有也可能沒有標題行,pandas 默認將第一行用作列名
In [46]: data = "a,b,c\n1,2,3\n4,5,6\n7,8,9"
In [47]: print(data)
a,b,c
1,2,3
4,5,6
7,8,9
In [48]: pd.read_csv(StringIO(data))
Out[48]:
a b c
0 1 2 3
1 4 5 6
2 7 8 9通過將 names 參數與 header 一起使用
In [49]: print(data)
a,b,c
1,2,3
4,5,6
7,8,9
In [50]: pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=0)
Out[50]:
foo bar baz
0 1 2 3
1 4 5 6
2 7 8 9
In [51]: pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=None)
Out[51]:
foo bar baz
0 a b c
1 1 2 3
2 4 5 6
3 7 8 9如果標題不在第一行中,可以將行號傳遞給 header,將會跳過前面的行
In [52]: data = "skip this skip it\na,b,c\n1,2,3\n4,5,6\n7,8,9"
In [53]: pd.read_csv(StringIO(data), header=1)
Out[53]:
a b c
0 1 2 3
1 4 5 6
2 7 8 9
5. 重複列名處理如果文件或表頭包含重複的名稱,默認情況下 pandas 會將它們區分開,以防止數據覆蓋
In [54]: data = "a,b,a\n0,1,2\n3,4,5"
In [55]: pd.read_csv(StringIO(data))
Out[55]:
a b a.1
0 0 1 2
1 3 4 5默認情況下,mangle_dupe_cols=True 會使用 .N 的方式標記重名的列,如果設置 mangle_dupe_cols=False 將會出現重複的列
In [2]: data = 'a,b,a\n0,1,2\n3,4,5'
In [3]: pd.read_csv(StringIO(data), mangle_dupe_cols=False)
Out[3]:
a b a
0 2 1 2
1 5 4 5為了防止用戶遇到重複數據的問題,現在,如果 mangle_dupe_cols != True,則會引發 ValueError 異常:
In [2]: data = 'a,b,a\n0,1,2\n3,4,5'
In [3]: pd.read_csv(StringIO(data), mangle_dupe_cols=False)
...
ValueError: Setting mangle_dupe_cols=False is not supported yet
5.1 篩選列usecols 參數允許你選擇文件中指定的列,可以使用列名、位置或一個可調用的函數
In [56]: data = "a,b,c,d\n1,2,3,foo\n4,5,6,bar\n7,8,9,baz"
In [57]: pd.read_csv(StringIO(data))
Out[57]:
a b c d
0 1 2 3 foo
1 4 5 6 bar
2 7 8 9 baz
In [58]: pd.read_csv(StringIO(data), usecols=["b", "d"])
Out[58]:
b d
0 2 foo
1 5 bar
2 8 baz
In [59]: pd.read_csv(StringIO(data), usecols=[0, 2, 3])
Out[59]:
a c d
0 1 3 foo
1 4 6 bar
2 7 9 baz
In [60]: pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["A", "C"])
Out[60]:
a c
0 1 3
1 4 6
2 7 9usecols 參數還可以用於指定最終結果中不使用哪些列
In [61]: pd.read_csv(StringIO(data), usecols=lambda x: x not in ["a", "c"])
Out[61]:
b d
0 2 foo
1 5 bar
2 8 baz在這個例子中,我們排除了 a 和 c 列
6 注釋和空行6.1 忽略注釋行和空行如果指定了 comment 參數,則注釋的行將被忽略。默認情況下,空白的行也會被忽略
In [62]: data = "\na,b,c\n \n# commented line\n1,2,3\n\n4,5,6"
In [63]: print(data)
a,b,c
# commented line
1,2,3
4,5,6
In [64]: pd.read_csv(StringIO(data), comment="#")
Out[64]:
a b c
0 1 2 3
1 4 5 6如果設置 skip_blank_lines=False,則不會忽略空行和注釋行
In [65]: data = "a,b,c\n\n1,2,3\n\n\n4,5,6"
In [66]: pd.read_csv(StringIO(data), skip_blank_lines=False)
Out[66]:
a b c
0 NaN NaN NaN
1 1.0 2.0 3.0
2 NaN NaN NaN
3 NaN NaN NaN
4 4.0 5.0 6.0注意:被忽略的行可能會造成涉及行號的歧義,header 參數使用行號(忽略注釋/空行),而 skiprows 使用行號(包括注釋/空行)
In [67]: data = "#comment\na,b,c\nA,B,C\n1,2,3"
In [68]: pd.read_csv(StringIO(data), comment="#", header=1)
Out[68]:
A B C
0 1 2 3
In [69]: data = "A,B,C\n#comment\na,b,c\n1,2,3"
In [70]: pd.read_csv(StringIO(data), comment="#", skiprows=2)
Out[70]:
a b c
0 1 2 3如果 header 和 skiprows 都指定了,則 header 將相對於 skiprows 的末尾。例如
In [71]: data = (
....: "# empty\n"
....: "# second empty line\n"
....: "# third emptyline\n"
....: "X,Y,Z\n"
....: "1,2,3\n"
....: "A,B,C\n"
....: "1,2.,4.\n"
....: "5.,NaN,10.0\n"
....: )
....:
In [72]: print(data)
# empty
# second empty line
# third emptyline
X,Y,Z
1,2,3
A,B,C
1,2.,4.
5.,NaN,10.0
In [73]: pd.read_csv(StringIO(data), comment="#", skiprows=4, header=1)
Out[73]:
A B C
0 1.0 2.0 4.0
1 5.0 NaN 10.0
6.2 注釋有時文件中可能包含注釋或元數據:
In [74]: print(open("tmp.csv").read())
ID,level,category
Patient1,123000,x # really unpleasant
Patient2,23000,y # wouldn't take his medicine
Patient3,1234018,z # awesome默認情況下,解析器在輸出中包括注釋
In [75]: df = pd.read_csv("tmp.csv")
In [76]: df
Out[76]:
ID level category
0 Patient1 123000 x # really unpleasant
1 Patient2 23000 y # wouldn't take his medicine
2 Patient3 1234018 z # awesome我們可以使用 comment 關鍵字
In [77]: df = pd.read_csv("tmp.csv", comment="#")
In [78]: df
Out[78]:
ID level category
0 Patient1 123000 x
1 Patient2 23000 y
2 Patient3 1234018 z
7 處理 Unicode 數據encoding 參數應用於編碼 unicode 數據,它將導致字節字符串在結果中需要 unicode 解碼
In [79]: from io import BytesIO
In [80]: data = b"word,length\n" b"Tr\xc3\xa4umen,7\n" b"Gr\xc3\xbc\xc3\x9fe,5"
In [81]: data = data.decode("utf8").encode("latin-1")
In [82]: df = pd.read_csv(BytesIO(data), encoding="latin-1")
In [83]: df
Out[83]:
word length
0 Träumen 7
1 Grüße 5
In [84]: df["word"][1]
Out[84]: 'Grüße'一些情況下必須指定正確的解碼格式才能正確解析數據
8 索引列和末尾分隔符如果一個文件的數據列比列名多一列,第一列將被用作 DataFrame 的行名
In [85]: data = "a,b,c\n4,apple,bat,5.7\n8,orange,cow,10"
In [86]: pd.read_csv(StringIO(data))
Out[86]:
a b c
4 apple bat 5.7
8 orange cow 10.0In [87]: data = "index,a,b,c\n4,apple,bat,5.7\n8,orange,cow,10"
In [88]: pd.read_csv(StringIO(data), index_col=0)
Out[88]:
a b c
index
4 apple bat 5.7
8 orange cow 10.0通常,您可以使用 index_col 參數來實現此行為
當在每個數據行的末尾帶有一個分隔符的文件時,會出現一些異常情況,讓解析器感到頭大。要顯式禁用索引列推斷並放棄最後一列,可以設置 index_col=False
In [89]: data = "a,b,c\n4,apple,bat,\n8,orange,cow,"
In [90]: print(data)
a,b,c
4,apple,bat,
8,orange,cow,
In [91]: pd.read_csv(StringIO(data))
Out[91]:
a b c
4 apple bat NaN
8 orange cow NaN
In [92]: pd.read_csv(StringIO(data), index_col=False)
Out[92]:
a b c
0 4 apple bat
1 8 orange cow如果使用 usecols 參數提取數據的子集,index_col 的作用將基於該子集,而不是原始數據
In [93]: data = "a,b,c\n4,apple,bat,\n8,orange,cow,"
In [94]: print(data)
a,b,c
4,apple,bat,
8,orange,cow,
In [95]: pd.read_csv(StringIO(data), usecols=["b", "c"])
Out[95]:
b c
4 bat NaN
8 cow NaN
In [96]: pd.read_csv(StringIO(data), usecols=["b", "c"], index_col=0)
Out[96]:
b c
4 bat NaN
8 cow NaN注意:雖然使用了 usecols 參數,但是由於末尾的分隔符,導致數據的第一列作為索引而無法使數據正確對齊