前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python数据分析实战之数据获取三大招

Python数据分析实战之数据获取三大招

作者头像
数据STUDIO
发布2021-06-24 09:58:11
6.1K0
发布2021-06-24 09:58:11
举报
文章被收录于专栏:数据STUDIO

一个数据分析师,最怕的一件事情莫过于在没有数据的情况下,让你去做一个详细的数据分析报告。确实,巧妇难为无米之炊,数据是数据分析、数据挖掘乃至数据可视化最最基础的元素。

利用Python进行数据分析最重要到一步,就是利用合适的方法将数据导入到Python。然而,当你面对一堆数据,你真的会快速、正确的读取吗?

在本期Python数据分析实战学习中,将从常见的数据获取方法入手,对常用的数据获取方式进行详细的介绍:

  • Open( ) 函数读取数据
  • Pandas 库读取数据
  • Numpy 库读取数据

第一招 Open( )函数读取数据

Python内置函数open( ),主要用来从文本中读取数据。

Python可以读取任何格式的文本数据。一般分为三个步骤:定义数据文件、创建文件对象、读取文件内容。

  • 定义数据文件

语法

将文件赋值给一个文件对象,为了后续操作更加便捷,减少代码冗余。

代码语言:javascript
复制
file_name1 = './test.txt'
file_name2 = '/Users/jim/Documents/Python/test.txt'

file_name1为相对路径,其要求需脚本路径与文件路径一致。 file_name2:为绝对路径,无其他要求。

  • 创建文件对象

1、语法

要以读文件的模式打开一个文件对象,使用Python内置的open( )函数,传入文件名和标示符,其意义在于后续的操作均是基于该对象产生的。

代码语言:javascript
复制
file_object = open(name [, mode][, buffering])

name: 要读取的文件名称 mode: 打开文件的模式,选填。r, r+, w, w+, a, a+ 使用最多。 buffering: 文件所需的缓冲区大小, 选填。0表示无缓冲, 1表示线路缓冲。

Mode

Describe

r

以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

w

打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

a

打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

rb

以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。

rb+

以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。

r+

打开一个文件用于读写。文件指针将会放在文件的开头。

w+

打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

a+

打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

wb

以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

wb+

以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

ab

以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

ab+

以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

代码语言:javascript
复制
>>> file_object = open(file_name, 'r')

# 文件不存在,即报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: './test.txt'

>>> file_object.read()
'Hello world!'

2、Python基于文件对象分为3种方法

hon基于文件对象分为3种方法

Methods

Describe

Return

read

读取文件中的全部数据,直到到达定义的size字节数上限

内容字符串,所有行合并为一个字符串

readline

读取文件中的一行数据,直到到达定义的size字节数上限

内容字符串

readlines

读取文件中的全部数据,直到到达定义的size字节数上限

内容列表,每行数据作为列表中的一个对象

代码语言:javascript
复制
# test.txt中有两行内容:
"""
line1: Hello world!
line2: Life is short. I learn Python!
"""

>>> file_object = open(file_name)
>>> read_data = file_object.read()
>>> print(read_data)
line1: Hello world!
line2: Life is short. I learn Python!

>>> readline_data = file_object.readline()
>>> print(readline_data)
line1: Hello world!

>>> readlines_data = file_object.readlines()
>>> print(readlines_data)
line1: Hello world!
line2: Life is short. I learn Python!

遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open( )函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

代码语言:javascript
复制
file_object = open('/Users/jim/Documents/Python/gbk.txt', 'r', encoding='gbk', errors='ignore' )

readline 每次只读取一行数据,需配合seek, next等指针操作,才能完整遍历所有数据记录。

代码语言:javascript
复制
>>> fout = open('text.txt')  # 获得文件对象
>>> print(fout.tell())  # 输出指针位置
0

>>> line1 = fout.readline()  # 获得文件第一行数据
>>> print(line1)  # 输出第一行数据
line1: Hello world!
>>> print(fin.tell())  # 输出指针位置
21

>>> line2 = fout.readline()  # 获得文件第二行数据
>>> print(line2)  # 输出第二行数据
line2: Life is short. I learn Python!

>>> print(fout.tell())  # 输出指针位置
>>> fout.close()  # 关闭文件对象
60

由于文件读写时都有可能产生IOError,一旦出错,后面的fout.close()就不会调用。可以使用try … finally来保证无论是否出错都能正确地关闭文件:

代码语言:javascript
复制
>>> try:
...   file_object = open('./text.txt', 'r')
...   print(file_object.read())
... finally:
...   if file_object:
...     file_object.close()

3、基于with的文件打开方法

相信很多时候,在使用open( )函数时,总不是很方便。此时使用基于with的文件打开方法,可以自动做上下文管理,而无需单独做close操作,简单又方便:

例1 对单个文件对象操作时:

代码语言:javascript
复制
>>> with open( './test.txt', 'r' ) as fout:
...   print(fout.read())
line1: Hello world!
line2: Life is short. I learn Python!

例2 同时对多个文件对象操作,可以连续写open方法:

代码语言:javascript
复制
>>> with open( './test1.txt', 'r' ) as fout1, open( './test2.txt', 'r' ) as fout2:
...   content1 = fout1.read()
...   content2 = fout2.read()

调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了。可以反复调用read(size)方法,每次最多读取size个字节的内容。 调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。 如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。


第二招 Pandas 库读取数据

在日常数据分析中,使用pandas读取数据文件更为常见。pandas不仅可以读取open()函数所读取的文本文件及其他各类文件,最重要的是pandas读取结果为DataFrame数据框,后续的数据处理更为方便。

1、语法

以最常用的读取csv文本文件数据为例,对pandas读取数据进行详细对介绍。

代码语言:javascript
复制
>>> import pandas as pd
>>> df = pd.read_csv(r"./test.csv"    # 路径里面可以是中文,到时如果有特殊字符,可能会报错,建议路径全是英文。
                 , sep = ','     # 默认分隔符为,
                 , header = 'infer' # 默认将第一行作为列名 ,header = None不要一第一行作为标题。
                 , encoding='gbk' # 默认用 UTF-8 进行解码,读取window系统建立的csv文件需改成`encoding='gbk'`
                 , index_col=None
                )
                 
>>> df.head(4)   # df.head()默认显示前5行, 当然可以自己制定sh

输出结果:

常用参数说明:

sep : str, default ‘,’ 指定分隔符。如果不指定参数,则会尝试使用逗号分隔。分隔符长于一个字符并且不是‘\s+’,将使用python的语法分析器。并且忽略数据中的逗号。正则表达式例子:'\r\t' header : int or list of ints, default ‘infer’ 指定行数用来作为列名,数据开始行数。如果文件中没有列名,则默认为0,否则设置为None。如果明确设定header=0 就会替换掉原来存在列名。header参数可以是一个list例如:[0,1,3],这个list表示将文件中的这些行作为列标题(意味着每一列有多个标题),介于中间的行将被忽略掉(例如本例中的2;本例中的数据1,2,4行将被作为多级标题出现,第3行数据将被丢弃,DataFrame的数据从第5行开始。)。注意:如果skip_blank_lines=True 那么header参数忽略注释行和空行,所以header=0表示第一行数据而不是文件的第一行。 index_col : int or sequence or False, default None 用作行索引的列编号或者列名,如果给定一个序列则有多个行索引。 如果文件不规则,行尾有分隔符,则可以设定index_col=False 来是的pandas不适用第一列作为行索引。 encoding : str, default None 指定字符集类型,通常指定为'utf-8'. dtype : Type name or dict of column -> type, default None 每列数据的数据类型。例如 {‘a’: np.float64, ‘b’: np.int32} nrows : int, default None 需要读取的行数(从文件头开始算起) skiprows : list-like or integer, default None 需要忽略的行数(从文件开始处算起),或需要跳过的行号列表(从0开始)。 low_memory : boolean, default True 分块加载到内存,再低内存消耗中解析。但是可能出现类型混淆。确保类型不被混淆需要设置为False。或者使用dtype 参数指定类型。注意使用chunksize 或者iterator 参数分块读入会将整个文件读入到一个DataFrame,而忽略类型(只能在C解析器中有效) parse_dates : boolean or list of ints or names or list of lists or dict, default False

  • boolean. True -> 解析索引
  • list of ints or names. e.g. If [1, 2, 3] -> 解析1,2,3列的值作为独立的日期列;
  • list of lists. e.g. If [[1, 3]] -> 合并1,3列作为一个日期列使用
  • dict, e.g. {‘foo’ : [1, 3]} -> 将1,3列合并,并给合并后的列起名为"foo"

2、常见问题

  • 路径内有中文csv
代码语言:javascript
复制
>>> import pandas as pd
>>> #df=pd.read_csv("E:/测试文件夹/测试数据.csv")
>>> f=open("E:/测试文件夹/测试数据.csv") # 解决方案
>>> df=pd.read_csv(f)
  • window 中 shift+右键-->复制为路径 获取的文件路径
代码语言:javascript
复制
>>> import pandas as pd
>>> # df=pd.read_csv("E:\测试文件夹\测试数据.csv")
>>> df=pd.read_csv(r"E:\测试文件夹\测试数据.csv")

字符串前加 r 的作用

代码语言:javascript
复制
>>> "E:\测试文件夹\测试数据.csv"
'E:\\测试文件夹\\测试数据.csv'

>>> r"E:\测试文件夹\测试数据.csv"
'E:\\测试文件夹\\测试数据.csv'

>>> print("E:\测试文件夹\test.csv")
E:\测试文件夹   est.csv
  
>>> print(r"E:\测试文件夹\test.csv")
E:\测试文件夹\test.csv
  • 排除某些行
代码语言:javascript
复制
>>> import pandas as pd
>>> df = pd.read_csv(r"./test.csv" 
...                  , skiprows=3 # 要注意的是:排除前3行是skiprows=3 排除第3行是skiprows=[3]
...                  , nrows=2
...                  , encoding='gbk')           
>>> df

输出结果:

  • 文件中有日期时间列
代码语言:javascript
复制
>>> import pandas as pd
>>> df = pd.read_csv(r"./test.csv", encoding='gbk'
...                  #, parse_dates=[3]
...                  )
>>> df.loc[0,'就诊日期']
2018/6/15
                 
>>> df = pd.read_csv(r"./test.csv", encoding='gbk'
...                 , parse_dates=[3]
...                )
>>> df.loc[0,'就诊日期']
Timestamp('2018-06-15 00:00:00')

避坑指南:

有日期时间格式列的文件作为缓存文件,先用test.to_csv('test.csv') 保存,再用pd.read_csv('./test.csv')读取文件时。 坑1:index列。保存文件时默认保存索引,读取文件时默认自动添加索引列,即将保存的索引作为第一列读取到DataFrame。 解决方案: 1,test.to_csv('test.csv', index=False) 2, pd.read_csv('./test.csv', index_col=0)


坑2:原本日期格式的列,保存到csv文件后仍为日期格式。但再次读取文件时将以字符串的格式读取到DataFrame。 解决方案: 1, pd.read_csv('./test.csv', parse_dates=[3]) 将特定的日期列解析为日期格式; 2, 先使用默认值file = pd.read_csv('./test.csv'),再对特定的列进行格式转换。file.loc[:, column] = file.loc[:, column].map(lambda x: parse(x).date() if isinstance(file.loc[0, column], str) else x)


更多详情,请见 pandas 官方文档查阅地址:

https://pandas.pydata.org/pandas-docs/version/0.24/reference/io.html


第三招 Numpy 库读取数据

Numpy读取数据方法与Pandas类似,其包括loadtxt, load, fromfile

Methods

Describe

Return

loadtxt

从txt文本中读取数据

从文件中读取的数组

load

使用numpy的load方法可以读取numpy专用的二进制数据文件,从npy, npz或pickled文件中加载数组或pickled对象

从数据文件中读取的数据、元祖、字典等

fromfile

使用numpy的fromfile方法可以读取简单的文本文件数据以及二进制数据

从文件中读取的数据

  • 使用 loadtxt 方法读取数据文件

数据通常是一维或者二维的

语法

代码语言:javascript
复制
np.loadtxt( fname
           , dtype=<class 'float'>
           , comments='#'
           , delimiter=None
           , converters=None
           , skiprows=0
           , usecols=None
           , unpack=False
           , ndmin=0
           , encoding='bytes'
           , max_rows=None
           ,)

常用参数说明:

fname : file, str, or pathlib.Path 文件或字符串, 必填项, 指要读取的文件名称或字符串, 支持压缩的数据文件, 包括gzbz格式。 dtype : data-type, optional 数据类型, 选填, 默认为float。 comments : str or sequence of str, optional 字符串或字符串组成的列表, 选填,默认 #, 是表示注释字符集开始的标志。 delimiter : str, optional 字符串, 选填, 默认空格, 用来分隔多个列的分隔符, 如逗号、TAB符。 converters : dict, optional 字典, 选填, 默认为空, 用来将特定列的数据转换为字典中对应的函数的浮点型数据。如果第0列是一个date则'converters = {0: datestr2num} '; 'converters = {3: lambda s: float(s.strip() or 0)}' skiprows : int, optional 跳过特定行数据, 选填, 默认为0, 用来跳过特定前N条记录。 usecols : int or sequence, optional 整数或元祖, 选填, 默认为空, 用来指定要读取数据的列, 如(1, 3, 6) unpack : bool, optional 布尔值, 选填, 默认为False, 用来指定是否转置, 如果为True, 则转置 ndmin : int, optional 整数型, 选填, 默认为0, 用来指定返回的数据至少包含特定维度的数组, 值域为0/1/2 encoding : str, optional 字符串, 选填, 用于解码inputfile的编码。不适用于输入流。特殊值 "bytes" 允许向后兼容解决方案, 这可以确保接收到字节数组作为结果, 如果可能的话“latin1”编码的字符串到转换器。重写此值以接收unicode数组, 并将字符串作为输入传递给转换器。如果没有设置, 使用系统默认值。默认值是"bytes"max_rows : int, optional 整数, 选填, 默认为空, 在"skiprows"行之后读取内容的"max_rows"行。默认的就是读所有的行。

代码语言:javascript
复制
>>> import numpy as np  # 导入numpy库
>>> file_name = 'numpy_data.txt'  # 定义数据文件
>>> data = np.loadtxt(file_name, dtype='float32', delimiter=' ')  # 获取数据
>>> print(data)  # 打印数据
[[ 0.  1.  2.  3.  4.]
 [ 5.  6.  7.  8.  9.]
 [10. 11. 12. 13. 14.]]
  • 使用 load 方法读取数据文件

使用numpyload方法可以读取numpy专用的二进制数据文件,从npy, npzpickled文件中加载数组或pickled对象, 该文件通常基于numpysavesavez产生。

语法

代码语言:javascript
复制
np.load(file
        , mmap_mode=None
        , allow_pickle=False
        , fix_imports=True
        , encoding='ASCII')

file : file-like object, string, or pathlib.Path 类文件对象或字符串格式, 必填, 要读取的文或字符串。类文件对象需要支持seek()read()方法。 mmap_mode : {None, 'r+', 'r', 'w+', 'c'}, optional 内存映射模式, 选填。 allow_pickle : bool, optional 布尔值, 选填, 默认为True, 决定是否允许加载存储在npy文件中的pickled对象数组。 fix_imports : bool, optional 布尔值, 选填, 默认为True, 只有在python3上加载python2生成的pickle文件时才有用, 其中包括包含对象数组的npy/npz文件。如果"fix_imports", 如果是True, pickle将尝试将旧的python2名称映射到新名称在python3中使用。 encoding : str, optional 在读取Python 2字符串时使用什么编码。加载python2生成了python3中的pickle文件时才有用, 其中包括包含对象数组的npy/npz文件。除了latin1, "ASCII""bytes"是不允许的, 因为它们会破坏数字数据。默认值: "ASCII"

代码语言:javascript
复制
>>> import numpy as np  # 导入numpy库
>>> write_data = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])  # 定义要存储的数据
>>> np.save('load_data', write_data)  # 保存为npy数据文件
>>> read_data = np.load('load_data.npy')  # 读取npy文件
>>> print(read_data)  # 输出读取的数据
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
  • 使用 fromfile 方法读取数据文件

该方法读取的数据来源于numpy的tofile方法。

语法

代码语言:javascript
复制
fromfile(file, dtype=float, count=-1, sep='', offset=0)

file : file or str or Path 文件或字符串或路径 dtype : data-type, optional 数据类型, 选填, 默认为float。 count : int 整数型, 读取数据的数量, -1意味着读取所有的数据。 sep : str 字符串, 如果文件是文本文件, 那么该值为数据间的分隔符。空("")分隔符表示该文件应该作为二进制文件处理。分隔符中的空格(" ")匹配零个或多个空格字符。仅由空格组成的分隔符必须至少匹配一个空白。

代码语言:javascript
复制
>>> import numpy as np  # 导入numpy库
>>> file_name = 'numpy_data.txt'  # 定义数据文件
>>> data = np.loadtxt(file_name, dtype='float32', delimiter=' ')  # 获取数据
>>> tofile_name = 'binary'  # 定义导出二进制文件名
>>> data.tofile(tofile_name)  # 导出二进制文件
>>> fromfile_data = np.fromfile(tofile_name, dtype='float32')  # 读取二进制文件
>>> print(fromfile_data)  # 打印数据
[ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14.]

另外,使用Python读取Excel文件,除了使用pandas.read_excel(),还是采用专门用于读取Excel的第三方库,最常用的是xlrd。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据STUDIO 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档