一、数据读取
在Python中,数据读取是一个常见的操作,特别是在数据分析、机器学习、数据库管理和文件处理等领域。在本博客中为方便后续的读取与字符串的转换,这里调用了医疗花费预测训练数据用于原始数据来实现数据的读取,医疗花费预测数据中有着训练集和测试集两个csv文件(csv文件之间是以“,”来进行隔开),这里以训练集数据来实现数据的读取操作。
以下是一些常用的数据读取方法,涵盖了不同类型数据源的读取操作:
1.1 使用pandas库读取数据
pandas
是一个强大的 Python 数据分析库,它提供了非常方便的函数来读取和写入 CSV 文件。以下是如何使用 pandas
读取 CSV 文件的基本步骤:
pandas库是一个第三方库,在使用pandas库时需要先进行库的安装
# python的pip安装pandas库
pip install pandas
# conda上安装pandas库
conda install pandas
使用pandas库的read_csv()函数进行数据的读取
import pandas as pd
# 读取csv文件,在使用pandas库读取时局时必须要有列名
df = pd.read_csv("第6章 医疗花费预测/train.csv")
# 查看数据前几行
print(df.head())
# 读取数据的特定列,使用索引列名的方式来进行数据的读取
print(df['age'])
# 读取多行数据时可以使用zip来进行数据的迭代
for i in zip(df['age'],df['charges']):
print(i)
运行的结果如下
在使用read_csv读取数据时数据中难免会因为格式不对、读取错误而产生缺失值(nan),对于产生的缺失值可以采用删除缺失值的行(这种是产生缺失值相对于整个数据集很小的情况下)、使用特定的值来填补(使用''"来进行数据的占位)等等。
缺失值的删除
使用read_csv函数自带的keep_default_na(将默认的nan,NaT视为缺失值)默认为True
import pandas as pd
# 使用read_csv函数自带的keep_default_na(将默认的nan,NaT视为缺失值)默认为True
df = pd.read_csv("第6章 医疗花费预测/train.csv", keep_date_col=True)
# 对缺失值进行行删除
df.dropna()
# 对缺失值进行列删除,但不建议删除列
df.dropna(axis=1)
对于存在没有在默认缺失值中的数据,但存在异常,可以使用na_values
参数允许你指定哪些值应该被视为缺失值。
import pandas as pd
# 使用na_value参数可以添加一些默认库所没有的缺失值类型
df = pd.read_csv("第6章 医疗花费预测/train.csv", na_values=['?'])
# 对缺失值进行行删除
df.dropna()
# 对缺失值进行列删除,但不建议删除列
df.dropna(axis=1)
对于一些原始数据中存在着空字符串或者空值的情况并且不是缺失值时(默认情况下read_csv函数会将空字符串当做缺失值),使用na_filter参数来过滤掉空字符串等情况,默认情况下是True表示会将空字符串等作为缺失值。
import pandas as pd
# 使用na_filter参数表示把空字符串等过滤掉
df = pd.read_csv("第6章 医疗花费预测/train.csv", na_filter=False)
# 对缺失值进行行删除
df.dropna()
# 对缺失值进行列删除,但不建议删除列
df.dropna(axis=1)
缺失值的填充
对于缺失值的填充使用fillna()函数来进行缺失值填充
import pandas as pd
# 使用na_filter参数表示把空字符串等过滤掉
df = pd.read_csv("第6章 医疗花费预测/train.csv", na_filter=False)
# 对于缺失值的填充
df.fillna('')
在这里介绍一下pandas库的read_csv()函数的参数
pandas.read_csv(filepath_or_buffer, sep=',', delimiter=None, header='infer',
names=None, index_col=None, usecols=None, squeeze=False, prefix=None,
mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None,
false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None,
na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True,
parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None,
dayfirst=False, iterator=None, chunksize=None, compression='infer', thousands=None,
decimal=b'.', lineterminator=None, quotechar='"', quoting=0, escapechar=None, comment=None,
encoding=None, dialect=None, error_bad_lines=False, warn_bad_lines=True, on_bad_lines=None,
delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)
- filepath_or_buffer:文件路径、URL 或文件对象。如果是文件路径,可以是相对路径或绝对路径。
- sep 或 delimiter:字段的分隔符,默认为逗号(
,
)。 - header:指定作为列名的行,默认为0(第一行)。如果设置为
None
,则没有行用作列名。 - names:列名列表,用于没有列名的 CSV 文件。
- index_col:指定作为行索引的列。
- usecols:需要读取的列名列表或列索引列表。
- dtype:指定列的数据类型。
- skiprows:跳过的行数或要跳过的行的列表。
- nrows:要读取的行数。
- na_values:将这些值视为缺失值。
- keep_default_na:是否保留默认的缺失值(如
NA
、NaN
)。 - parse_dates:解析日期的列。
- infer_datetime_format:如果为
True
,pandas
将尝试自动推断日期时间格式。 - iterator:返回一个迭代器而不是
DataFrame
。 - chunksize:返回一个可迭代的对象,每次迭代返回
chunksize
行。 - compression:文件压缩类型,如
'gzip'
、'bz2'
等。 - encoding:文件编码。
Python 中的 zip
函数是一个非常有用的内置函数,它属于迭代器,可以将多个可迭代对象(如列表、元组、字符串等)中的元素打包成一个个的元组,然后返回由这些元组组成的迭代器。zip
函数通常用于将两个或多个列表中的对应元素配对。
zip(*iterables, fillvalue=None)
- iterables:一个或多个可迭代对象。
- fillvalue:如果各个迭代器的长度不一致,
zip
会停止在最短的迭代器结束时。如果指定了fillvalue
,则会在较短的迭代器耗尽时用该值填充。
1.2 使用python的内置库(csv)读取数据
Python的csv
库是一个内置的模块(csv是内置模块,使用前无需下载),专门用于读取和写入CSV(逗号分隔值)文件。CSV文件是一种常见的数据交换格式,因为它简单且被广泛支持。csv
模块提供了一系列的工具,使得处理CSV文件变得容易。
csv库内置很多的核心组件用于数据的读写,下面是几种常见的组件:
1.csv.reader:用于从文件或类似文件的对象中读取CSV格式的数据。
2.csv.writer:用于将数据写入文件或类似文件的对象,生成CSV格式。
3.csv.DictReader:类似于csv.reader
,但是将每行数据读取为字典,其中字段名由CSV文件的第一行提供。
4.csv.DictWriter:类似于csv.writer
,但是写入的是字典,其中字典的键对应CSV文件的列标题。
5.csv.register_dialect:用于注册或创建一个新的CSV方言(dialect),定义了特定的CSV格式。
6.csv.get_dialect:根据名称获取一个已注册的CSV方言。
7.csv.list_dialects:返回所有已注册CSV方言的列表。
8.csv.field_size_limit:用于设置或返回最大的字段大小。
1.2.1 csv.reader()
本次主要使用csv.reader()函数来进行数据的读取,读取的操作如下面的代码所示
import csv
"""
使用with(上下文管理器,用于管理数据的上下文的对接和读取数据后的关闭操作)
open函数用于打开文件并将数据封装到file文件对象中。
"""
with open("第6章 医疗花费预测/train.csv", 'r') as file:
# 创建一个阅读器(迭代器)对象存储文件对象中的数据
reader = csv.reader(file)
print(reader)
# 输出的格式为<_csv.reader object at 0x0000029060D59120>文件地址
# 当不需要列名的时候可以使用next函数来跳转到下一行
next(reader, None)# 可选操作
# 使用reader函数读取出的是一串封装的地址并不能直接使用,如果需要使用该数据需要将数据封装到一个列表对象中用于后续的读取操作
data = [row for row in reader]
print(data)
# 输出的格式为[[],[],[]]
# 遍历输出封装的列表对象数据
for i in data:
print(i)
运行的结果如下
1.2.2 csv.DictReader()
本次使用csv.DictReader函数(csv.DictReader函数会将读取的数据以列名作为键,里面的数据作为值)进行数据的读取,读取的代码如下
import csv
"""
使用with(上下文管理器,用于管理数据的上下文的对接和读取数据后的关闭操作)
open函数用于打开文件并将数据封装到file文件对象中。
"""
with open("第6章 医疗花费预测/train.csv", 'r') as file:
# 创建一个阅读器(迭代器)对象存储文件对象中的数据
reader = csv.DictReader(file)
print(reader)
# 输出的格式为<csv.DictReader object at 0x0000025C11770390>文件地址
# 使用DictReader函数读取出的是一串封装的地址并不能直接使用,如果需要使用该数据需要将数据封装到一个列表对象中用于后续的读取操作
data = [row for row in reader]
# 输出的格式为[{},{},{}],以字典的形式进行数据
for i in data:
# 可以通过索引列名进行索取字典中的值
print(i,i['age'])
运行的结果如下
在 Python 中,csv
库是一个内置库,用于读取和写入 CSV 文件。但是,csv
库本身并不提供直接处理缺失值的功能。处理缺失值通常需要在读取 CSV 文件之后,使用 Python 基本的字符串操作或者正则表达式来完成。
csv.reader()函数读取缺失值的过滤
csv.reader()函数读取出的数据是[[],[],[]]格式,里面按顺序存储
import csv
"""
使用with(上下文管理器,用于管理数据的上下文的对接和读取数据后的关闭操作)
open函数用于打开文件并将数据封装到file文件对象中。
"""
with open("第6章 医疗花费预测/train.csv", 'r') as file:
# 创建一个阅读器(迭代器)对象存储文件对象中的数据
reader = csv.DictReader(file)
print(reader)
# 输出的格式为<csv.DictReader object at 0x0000025C11770390>文件地址
# 使用DictReader函数读取出的是一串封装的地址并不能直接使用,如果需要使用该数据需要将数据封装到一个列表对象中用于后续的读取操作
data = [row for row in reader]
# 输出的格式为[{},{},{}],以字典的形式进行数据
missing_values = ["", "N/A", "#N/A", "NaN"] # 定义可能的缺失值表示
cleaned_data = []
for row in data:
cleaned_row = []
for value in row:
# 将值统一转换为字符串,然后检查是否为缺失值
value = str(value)
if value not in missing_values:
cleaned_row.append(value)
else:
cleaned_row.append(None) # 或者可以替换为特定的值,如0或自定义的标记
cleaned_data.append(cleaned_row)
# cleaned_data已经使用None标记了缺失值,后续可以对缺失值进行删除与替换
print(cleaned_data)
csv.DictReader()函数缺失值的处理
csv.DictReader()函数读取出的是[{},{},{}]格式,里面以字典的形式进行储存。
import csv
missing_values = ["", "N/A", "#N/A", "NaN"] # 定义可能的缺失值表示
cleaned_data = []
"""
使用with(上下文管理器,用于管理数据的上下文的对接和读取数据后的关闭操作)
open函数用于打开文件并将数据封装到file文件对象中。
"""
with open("第6章 医疗花费预测/train.csv", 'r') as file:
# 创建一个阅读器(迭代器)对象存储文件对象中的数据
reader = csv.DictReader(file)
print(reader)
# 输出的格式为<csv.DictReader object at 0x0000025C11770390>文件地址
# 使用DictReader函数读取出的是一串封装的地址并不能直接使用,如果需要使用该数据需要将数据封装到一个列表对象中用于后续的读取操作
# 对值进行判断是否为缺失值,如果是标记为None用于后续的替换或者删除
for row in reader:
cleaned_row = {key: value if value not in missing_values else None for key, value in row.items()}
cleaned_data.append(cleaned_row)
# 缺失值的替换
for row in cleaned_data:
for key, value in row.items():
if value is None: # 检查是否为缺失值
row[key] = "" # 替换为 "Unknown" 或其他合适的值
# 缺失值的删除
cleaned_data = [row for row in cleaned_data if None not in row.values()]
csv库读取数据时使用open()函数来实现,open
函数是Python内置的一个函数,用于打开一个文件,并返回一个文件对象。这个文件对象可以用于后续的文件操作,比如读取、写入等。以下是open
函数的一些基本用法和参数的详解:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
-
file:必需的参数,指定要打开的文件的路径。
-
mode:可选参数,用于指定文件打开的模式。默认是
'r'
,即只读模式。其他常见的模式包括:-
'r'
:只读模式。这是默认值。 -
'w'
:写入模式。如果文件已存在,则覆盖文件;如果文件不存在,则创建新文件。 -
'a'
:追加模式。如果文件已存在,则在文件末尾追加内容;如果文件不存在,则创建新文件。 -
'b'
:二进制模式。用于读写二进制文件。 -
't'
:文本模式。这是默认值。 -
'+'
:更新模式。用于读写文件。
模式可以组合使用,例如
'rb'
(二进制只读模式)、'wt'
(文本写入模式)等。 -
-
buffering:可选参数,用于设置缓冲区的大小。默认是
-1
,这意味着使用系统默认的大小(通常是8KB)。设置为0
表示不使用缓冲,每个I/O操作都会直接传递到底层的系统调用。 -
encoding:可选参数,用于指定文件的编码。默认是
None
,这意味着使用系统默认的编码。对于文本文件,通常需要指定正确的编码,比如'utf-8'
。 -
errors:可选参数,用于指定如何处理编码或解码错误。常见的值包括
'strict'
(默认值,出错时抛出异常)、'ignore'
(忽略错误)和'replace'
(用一个特殊字符替换错误字符)。 -
newline:可选参数,用于控制行结束符的行为。默认是
None
,这意味着行结束符会被转换为系统默认的行结束符。可以设置为'\n'
、'\r'
或'\r\n'
来控制行结束符。 -
closefd:大多数情况下用不到,只有在
open
被给定了一个已经打开的文件描述符时才需要。默认是True
,意味着在文件关闭时,底层的文件描述符也会被关闭。 -
opener:可选参数,用于指定一个自定义的函数来打开文件。这允许使用特定的系统调用或其他机制来打开文件。
with
语句是Python中的一个上下文管理器(context manager),它用于封装一组操作,这些操作需要建立一个环境,然后执行一些代码,最后清理环境。使用with
语句可以简化资源管理,如文件操作、数据库连接等,因为它会自动帮你处理资源的获取和释放。
1.3 使用numpy库读取数据
在Python中使用NumPy库读取CSV文件是一个简单的过程。NumPy提供了一个名为numpy.genfromtxt
的函数,可以用来读取CSV文件。以下是使用NumPy读取CSV文件的基本步骤:
在使用numpy库读取数据之前需要再终端上安装numpy库(numpy是一个第三方库)
# 在python终端上安装numpy库
pip install numpy
# 在conda上安装numpy库
conda install numpy
使用numpy.genfromtxt
函数读取CSV文件。这个函数默认会将数据读取为浮点数,但你也可以指定数据类型。在处理缺失值的时候使用后filling_values=''"来替换缺失值处理。
import numpy as np
# 使用np.genfromtxt函数读取数据时,这次的文件为数字与英语混合读取,
# 如果不设置dtype会出现读取因为为空的场景
# 设置filling_values=''是将所有的缺失值替换为''(空字符串)
data = np.genfromtxt("第6章 医疗花费预测/train.csv",delimiter=',',
dtype=str,encoding='utf-8', filling_values='')
# 获取的数据是以列表的数组的形式进行存储,可以调用[][]来获取数据
print(data[1])
运行结果如下
np.genfromtxt
是 NumPy 库中的一个函数,用于从文本文件中读取数据。这个函数非常灵活,可以处理各种数据类型,包括数值型和字符串型数据,并且能够处理缺失数据和注释。下面是np.genfromtxt
函数的详细参数:
numpy.genfromtxt(fname, dtype=<class 'float'>, comments='#',
delimiter=None, skip_header=0, skip_footer=0, converters=None,
missing_values=None, filling_values=None, usecols=None, names=None,
excludelist=None, deletechars=" !#$%&'()*+, -./:;<=>?@[\\]^{|}~",
replace_space='_', autostrip=False, case_sensitive=True,
defaultfmt='f%i', unpack=None, usemask=False, loose=True,
invalid_raise=True, max_rows=None, encoding=None, *, ndmin=0, like=None)
fname
:文件名或文件对象,指向要读取的文本文件。dtype
:数据类型;如果为None
,则自动推断数据类型。comments
:注释字符,默认为#
,所有以该字符开头的行都会被忽略。delimiter
:列的分隔符,默认为空,此时函数会尝试自动检测分隔符。skip_header
:跳过文件开始的行数。skip_footer
:跳过文件末尾的行数。converters
:一个函数或字典,用于转换数据,可以针对特定的列进行自定义转换。missing_values
:被视为缺失值的值列表。filling_values
:用于填充缺失值的值。usecols
:指定要读取的列,可以是整数索引或列名。encoding
:文件编码,默认为bytes
,可以设置为utf-8
、latin1
等。
二、字符串类型的转换
假设读取的医疗花费预测数据用于机器学习的训练与预测,为了便于之后的一系列分析,首先需要将无法参与计算的字符串类型转换为整数类型。sklearn.preprocess包提供了方便的转换工具,可以直接将这些字符串类型的数据编码为相应的整数。
2.1 OrdinalEncoder编码器
OrdinalEncoder
是 scikit-learn 库中的一个预处理类,用于将分类特征转换为整数数组。主要用于处理有序的分类变量,它通过为每个类别分配一个整数值来保留类别之间的顺序关系。
可以使用OrdinalEncoder编码器中的fit_transform函数来将特定列的二维数组进行序数编码。OrdinalEncoder在对数据进行编码时按照下面的规格进行确定数字的编号的(即该字符出现的次数)
- 低 = 0
- 中 = 1
- 高 = 2
import pandas as pd
# 读取训练数据
train = pd.read_csv("第6章 医疗花费预测/train.csv")
# 查看前几行数据
print(train.head(5))
# 导入OrdinalEncoder编码器
from sklearn.preprocessing import OrdinalEncoder
# 创建编码器对象,将字符设置为int类型,如果不设置会为浮点类型
# numpy里的int已经被启用使用python自有的int类型
encoder = OrdinalEncoder(dtype=int)
# 使用fit_transform函数将sex,smoker,region编码为int类型便于后续的机器学习的预测
train[['sex', 'smoker', 'region']] = encoder.fit_transform(train[['sex', 'smoker', 'region']])
print(train.head(5))
运行结果如下:
fit_transform
函数是机器学习和数据预处理中常用的一个方法,尤其在 scikit-learn(sklearn)库中非常流行。这个函数结合了两个步骤:fit
和 transform
,通常用于训练数据(模型学习数据的特征)和转换数据(应用学习到的特征到数据上)。
fit_transform
通常用于以下场景:
- 特征缩放:如标准化(StandardScaler)和归一化(MinMaxScaler),使特征具有相同的尺度。
- 特征编码:如将分类特征转换为数值表示,例如使用 One-Hot 编码(OneHotEncoder)或序数编码(OrdinalEncoder)。
- 缺失值处理:如填充缺失值(SimpleImputer)。
fit_transform
函数详细介绍
- Fit:在训练数据上拟合模型。在特征缩放、编码或其他预处理步骤中,模型需要学习数据的特定属性,例如均值、标准差等。
- Transform:将拟合后的模型应用到数据上,以转换数据。这可能包括标准化数据、将分类变量转换为数值表示等。
2.2 OneHotEncoder编码器
OneHotEncoder
是一个在数据预处理中常用的工具,特别是在机器学习和统计建模中处理分类变量时。它的主要功能是将分类特征(也称为名义特征)转换为一种数值形式,使得这些特征可以被机器学习算法处理。
OneHotEncoder
在进行分类列表的数字编码时,是基于每个特征中出现的唯一值来进行的。对于每个分类特征,OneHotEncoder
会创建一个二进制向量,其中只有一个位置是1,其余位置是0,这个1的位置对应于该特征值的唯一类别,如果一个元素属于特定的类别,则对应的二进制值为1,否则为0。例如,如果一个特征有两个类别“A”和“B”,则会创建两个新列,一个类别“A”的列,另一个类别“B”的列。
OneHotEncoder
编码器会依据于分类列中的不同类别创建一个列,当该行数据存在这个特定类别则设置为1,如果不是则设置为0.
import pandas as pd
# 读取训练数据
train = pd.read_csv("第6章 医疗花费预测/train.csv")
# 查看前几行数据
print(train.head(5))
from sklearn.preprocessing import OneHotEncoder
# 确定哪些列包含分类数据(字符串类型)
categorical_columns = ['sex', 'smoker', 'region']
# 设置类型为int类型
encoder = OneHotEncoder(dtype=int)
# 将需要转换的分类别传入到fit_transform函数中,转换后的数据为一个稀疏矩阵
encoded_data = encoder.fit_transform(train[categorical_columns])
# 对生成的数据进行创建DataFrame用于存放数据,并将数据转化为稠密矩阵
# 使用get_feature_names_out可以将列进行一次很好的加载
encoded_df = pd.DataFrame(encoded_data.toarray(),
columns=encoder.get_feature_names_out(categorical_columns))
# 将两个DataFrame进行连接,将分类类别在原有DataFrame进行删除,并与分类DataFrame进行连接
train = pd.concat([train.drop(categorical_columns, axis=1), encoded_df], axis=1)
print(train.head(5))
运行结果如下:
get_feature_names_out
函数是 scikit-learn 中的一个方法,它用于获取经过转换器(transformer)处理后的输出特征名称。这个方法在处理管道(pipeline)或列转换器(ColumnTransformer)时特别有用,因为它可以帮助我们了解转换后的特征名称,这些名称可能会因为转换而发生变化。
以下是 get_feature_names_out
函数的一些主要作用:
-
获取转换后的特征名称:在使用诸如
OneHotEncoder
、StandardScaler
等转换器后,原始的特征名称可能会被替换或修改。get_feature_names_out
方法可以返回这些转换后的特征名称,这对于理解模型处理后的数据结构非常重要。 -
管道中的元数据传递:在构建管道时,
get_feature_names_out
方法可以与ColumnTransformer
结合使用,以确保在管道的每一步中传递正确的特征名称。这对于管道中后续步骤的元数据路由(metadata routing)至关重要。 -
自定义转换器:对于自定义的转换器,
get_feature_names_out
方法可以被重写,以返回转换后的特征名称。这对于创建复杂的数据处理流程和管道非常有用。 -
调试和验证:
get_feature_names_out
方法可以帮助调试和验证数据处理流程,确保每一步的输出特征名称符合预期。 -
特征选择和可视化:在进行特征选择或可视化时,了解转换后的特征名称可以帮助我们更好地分析和解释模型结果。
2.3 LabelEncoder编码器
LabelEncoder
是 scikit-learn 库中的一个预处理工具,它用于将类别型数据(通常是字符串类型的标签)转换为整数型数据。这对于机器学习模型来说非常重要,因为大多数模型需要数值型输入。
LabelEncoder只能对一维数组对象进行叙述编码,这里只能遍历每一行数据进行判断是否为字符串类型,是字符串类型就对该列进行类型转换,它的转换依据与OrdinalEncoder编码器转换类型一致,以类别出现的频次来进行辨别。
import pandas as pd
# 读取训练数据
train = pd.read_csv("第6章 医疗花费预测/train.csv")
# 查看前几行数据
print(train.head(5))
from sklearn.preprocessing import LabelEncoder
# 默认情况下是int,这里不用设置
le = LabelEncoder()
# 对原始DataFrame进行列名的遍历
for column in train.columns:
# 判断该列是否为字符串类型
if train[column].dtype == 'object': # 检查列的数据类型是否为字符串(object)
# 只能一列一列的转换LabelEncoder不能进行多列转换
train[column] = le.fit_transform(train[column])
print(train.head(5))
运行结果如下: