这一篇是数分学习的第二次打卡。第一次打卡结束后,群内公布了优秀笔记,观摩了大佬的笔记后,我将改进我的笔记,引入一些基础概念的说明与解释,而不是单纯的代码与运算结果。
这一次打卡是关于简单的数据清洗与特征处理,这是数据分析的第一步。
数据清洗在数据分析的过程中是十分必要的,因为,在实践的过程中,遇到的数据常常是有缺失的,有离群值的,需要经过一定的处理才能继续做后面的分析或建模。这一次,我们将学习缺失值、重复值、字符串和数据转换等基本操作,将数据清洗处理成我们可以运用的样子。
缺失值观察与处理
何谓缺失值,它是指我们在浏览数据时,看到的“NaN”或者“ ”,这些在数据分析的时候,都是无法使用的,结果会报错。我们就需要进行观察,然后选择合适的方法进行缺失值填充。常见的填充的方法有,均值填充,固定值填充,中位数填充,众数填充等。
缺失值观察
首先,查看每个特征缺失值个数,确定哪些特征值的数据需要进行处理。
dt.isnull().sum()
根据结果我们得知,Age, Cabin, Embarked三个特征值存在缺失数据,其中Cabin的缺失值最多。接着,我们浏览一下这3列的数据。
dt.Age #方法1
dt['Age'] #方法2
dt.iloc[:,5] #方法3
观察 Cabin,Embarked列的数据和上面是一样的方法,这里就不再展示。
探索:其实,除了用数据的方法展示缺失值情况,我们也可以使用可视化的方法展示缺失值情况,可能会更加直观。话不多说,直接上代码。
missing = dt.isnull() #missing变量保存了数据的缺失情况
sns.heatmap(missing,yticklabels=False, cbar=False, cmap=None)
plt.rcParams['font.sans-serif'] = ['SimHei'] #通过此设置,可以在绘图中展示中文
plt.title('缺失值', size=17, pad=13)
plt.show()
我们通过以下可视化的结果,可以非常直观的看出Cabin的缺失情况非常严重,Age比较严重,而 Embarked的确实情况就好得多。通过可视化展示的好处就是,不仅可以看出哪些有缺失,还可以看出缺失值在整体数据中所占的比例,便于我们思考后面的处理办法,是进行填充,抑或是直接丢失。
对缺失值进行处理
以处理age数据的缺失值填充为例子,展示一下常见的处理方法。
使用dropna()函数直接删除。因为,age的缺失值其实是很多的,即使我们使用方法填充了,但数据其实与原本的样子已经有了很大的差异,不利于后续的研究。于是接下来,重点介绍以下dropna()函数。
函数及其参数:dropna(axis,how,thresh,subset,inplace)
axis:是删除空值所在的行or列。参数默认值是0,代表的是删除空值所在的行。
how:有空值就删除,还是,全为空值时再删除。参数的值默值为‘any’,表示的是删除空值所在的行or列;当参数值等于‘all’,表示的是删除一整行或者是一整列都为空值的行or列,如果某一行或某一列,只有部分为空值则不会删除。
thresh:参数是一个整数n,当某列or行的缺失值小于n,那么就不要删除,将它保留下来。
subset:是指定删除特定行或列的空值所在的列或行。默认值为0,表示如果指定行x中有空值,则删除所在的列
inplace:自行选择是在原数据上处理,还是在副本上处理。默认值是“False”,表示后续处理是在副本上进行,不影响原数据。
————————————————
原文链接: https://blog.csdn.net/BaoITcore/article/details/123847927
dt.dropna()
当然我们也可以选择固定值进行填充,这时,就需要用到fillna()函数。下面再介绍以下这个函数及其参数。
fillna(axis,mthod,limit,inplace)
axis:是填充空值所在的行or列。参数默认值是0,代表的是按列填充,这与dropna()函数相反。
method:指的是填充的方式,如果为‘ffill’,则是将这个空值的前一个数据复制给这个空值;如果为‘bfill’,则是将这个空值的后一个数据复制给这个空值。如果不用这个参数,不声明即可。
limit:这个参数时限制填充的空值的个数,比如某一列有两个空值,我这里指定只填充一个空值,另一个空值不管它。
————————————————
原文链接: https://blog.csdn.net/BaoITcore/article/details/123847927
df.fillna(0) #零值填充
dt[dt['Age'] == np.nan] = 0 #第二种填充值得方法
重复值观察与处理
请查看数据中的重复值
查看重复值需要用到duplicated()函数,当且仅当两条记录中所有的数据都相等时duplicated函数才会判断为重复值。
dt[dt.duplicated()] #查看数据中的重复值
dt.duplicated().sum() #检查有多少重复值
dt.duplicated() #显示重复值的位置
对重复值进行处理
我们需要用到drop_duplicate()函数,它只能对DataFrame格式的数据处理,去除特定列下面的重复行。
drop_duplicates(keep, subset, inplace )
keep: {‘first’, ‘last’, False},默认为’first’
保留项。保留第一个(first)/最后一个(last)/不保留(False)重复的项
subset:默认所有列
指定的列。即需要删除哪些列中重复的项,列用’'说明,用,隔开
inplace : {‘True’,‘False’},默认为False
是否在原数据上修改。False表示另存一个副本
————————————————
原文链接: https://blog.csdn.net/qq_42453890/article/details/110916950
dt = dt.drop_duplicates() #删除整行有重复值的清理
new_dt=dt.drop_duplicates(['Age']) #删除数据记录中Age列值相同的记录
将前面清洗的数据保存为csv格式
dt.to_csv("test_clear.csv")
特征观察与处理
在后续的数据分析过程中,数值类型可以直接使用,但是文本类型数据无法直接使用,需要将其转化为数值类型才能使用。例如sex, Cabin等特征向量就是文本类型,为了模型的稳定性及鲁棒性会对连续变量进行离散化。文本型特征往往需要转换成数值型特征才能用于建模分析。
对年龄进行分箱(离散化)处理
何为分箱,就是将数据按照特定的条件进行分类,分箱的操作主要针对于连续变量。例如,把0-20,21-40,41-60,61-80,81-100分别归为一类,放到一个箱子。
下面以数据中的age为例,展示一下如何进行分箱操作。我们选择age这一列,将其平均分为五份,依次赋值1,2,3,4,5。
dt['AgeBand'] = pt.cut(df['Age'], 5,labels = [1,2,3,4,5])
也有另一种方法,将连续变量Age按10% 30% 50 70% 90%分为五个年龄段,并用分类变量12345表示。
dt['AgeBand'] = pd.qcut(dt['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels = [1,2,3,4,5])
对文本变量进行转换
首先,查看文本数据的变量名及种类。主要涉及到Sex, Cabin ,Embarked三列数据。
#方法1,使用value_counts()函数
df['Sex'].value_counts()
df['Cabin'].value_counts()
df['Embarked'].value_counts()
#方法2,使用unique()函数
df['Sex'].unique()
df['Cabin'].unique()
df['Embarked'].unique()
Sex的结果
Cabin的结果
Embarked的结果
接下来就要对文本类别数据进行处理了,将其转化为数字类型。根据文本类别的数量,我们会选择不同的方法。
当文本特征数量比较少的时候,例如这里的sex特征向量,就只有两种。我们就可以使用replace和map这两种方法。
#方法一: replace
df['Sex_num'] = df['Sex'].replace(['male','female'],[1,2])
#方法二: map
df['Sex_num'] = df['Sex'].map({'male': 1, 'female': 2})
当文本特征数量比较多的时候,例如这里的Cabin,Ticket特征向量,种类就有几十种。我们就应该使用LabelEncoder和OneHotEncoder这两种方法。
LabelEncoder()
LabelEncoder是用来对分类型特征值进行编码,即对不连续的数值或文本进行编码。
LabelEncoder(fit(y),fit_transform(y),inverse_transform(y),transform(y))
fit(y) :fit可看做一本空字典,y可看作要塞到字典中的词。
fit_transform(y):相当于先进行fit再进行transform,即把y塞到字典中去以后再进行transform得到索引值。
inverse_transform(y):根据索引值y获得原始数据。
transform(y) :将y转变成索引值。
for feat in ['Cabin', 'Ticket']:
lbl = LabelEncoder()
label_dict = dict(zip(df[feat].unique(), range(df[feat].nunique())))
dt[feat + "_labelEncode"] = dt[feat].map(label_dict)
dt[feat + "_labelEncode"] = lbl.fit_transform(dt[feat].astype(str))
OneHotEncoder
适用范围:离散特征的取值之间没有大小的意义,比如color:[red,blue],那么就使用one-hot编码。
第一种方法,我们选择pandas库就可以对离散型特征进行one-hot编码。
for feat in ["Age", "Embarked"]:
x = pd.get_dummies(df[feat], prefix=feat)
df = pd.concat([df, x], axis=1)
df.head()
第二种方法,我们可以使用OneHotEncoder()函数
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
dt=pd.concat([df['Age'],df['Embarked']],axis=1)
enc.fit(dt)
enc.get_feature_names()
enc.categories_
从纯文本Name特征里提取出Titles的特征
意思就是从nama列中提取Mr,Miss,Mrs等信息,单独成为一列Titles。我们常使用str.extract函数,用正则表达式提取我们需要的内容。
df['Title'] = df.Name.str.extract('([A-Za-z]+)\.', expand=False)