pythoncsv文件处理软件,Python 数据处理(十四)—— IO 工具 CSV 示例

3 分类类型

分类类型可以通过指定 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")

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]

4 列的命名和使用

4.1 处理列名

一个文件可能有也可能没有标题行,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 9

usecols 参数还可以用于指定最终结果中不使用哪些列

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.0

In [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 参数,但是由于末尾的分隔符,导致数据的第一列作为索引而无法使数据正确对齐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值