原文链接:https://blog.csdn.net/liz_zhong/article/details/49915287
用pandas进行数据分析,对数据预处理,以及简单例子说明
- concat
用于将2个DataFrame连接到一起,一般是将训练集与测试集连接在一起对属性值进行预处理。个人感觉这样处理是可以的,因为对属性值的处理一般要求数值越多越好,而且对训练集与测试集的数据预处理要求要是一样的。只要在训练模型的时候讲2者分开就行。
相同列合并到一起,不同时新建列,缺省值为NaN
df1 =DataFrame({'a':[1,2,3],'b':[4,5,6]})
df2 =DataFrame({'a':['a','b','c'],'c':['e','f','g']})
df = pd.concat([df1,df2])
print df
"""
a b c
0 1 4 NaN
1 2 5 NaN
2 3 6 NaN
0 a NaN e
1 b NaN f
2 c NaN g
"""
df.reset_index(inplace=True)
print df
"""
index a b c
0 0 1 4 NaN
1 1 2 5 NaN
2 2 3 6 NaN
3 0 a NaN e
4 1 b NaN f
5 2 c NaN g
"""
df.drop('index', axis=1,inplace=True)
print df
"""
a b c
0 1 4 NaN
1 2 5 NaN
2 3 6 NaN
3 a NaN e
4 b NaN f
5 c NaN g
"""
df =df.reindex_axis(df1.columns, axis=1)
print df
"""
a b
0 1 4
1 2 5
2 3 6
3 a NaN
4 b NaN
5 c NaN
"""
df.shape[0],df.shape[1]分别获取行数、列数
print df.shape[1],"columns:", df.columns.values
print "Row count:",df.shape[0]
"""
2 columns: ['a' 'b']
Row count: 6
"""
- map()
Series 或 DataFrame 的列都可以调用一个map()方法。该方法接受一个函数或字典作为参数,并将之应用于该列的每一个元素,将元素值映射为另一个值。多用于数据离散化。
df = DataFrame(np.arange(8).reshape(4,2),columns= ['a','b'])
df['c'] = df['a'].map(lambda x: x+1)
print df
"""
a b c
0 0 1 1
1 2 3 3
2 4 5 5
3 6 7 7
"""
也可以在原来列修改值。df['a'] =df['a']. map({xxx})
"""
a b
0 1 1
1 3 3
2 5 5
3 7 7
"""
lambda函数也可以用自定义函数实现
当元素值少时,可以直接用字典修改:
df1 =DataFrame({'a':['female','male'],'b':['male','female']})
df1['a'] =df1['a'].map({'female':0, 'male':1})
print df1
"""
a b
0 0 male
1 1 female
"""
- isin()
判断某一列元素是否属于列表里的元素,返回True False列表,如果为True,则对该行元素进行操作,False时不操作
df = DataFrame({'columns1':['a','b','c'],'columns2':['c','d','e']})
df.columns1[df.columns1.isin(['a','b'])]= 'cc'
print df
"""
columns1columns2
0 cc c
1 cc d
2 c e
"""
- 采用均值/出现次数设置missing值
df =DataFrame(np.arange(8).reshape(4,2),columns=['a','b'])
median =df.a.dropna().median()
print 'median:',median
"""
pingjunzhi:
median: 3.0
"""
对于一列非数字,例如字符,要找到出现频率最高的字符赋值给missing值
df2 = DataFrame({'a':['a','b','a'],'c':['e','f','g']})
freq_max =df2.c.dropna().mode().values
print 'freq_max:',freq_max
"""
freq_max: ['a']
"""
试了下,如果求列c,各频率相同,则返回空列表
- 属性数字化----枚举
某一属性,其值表示为字符,且范围较少时,可选择使用枚举进行数字化
用np.unique()生成唯一化后的元素,在用enumerate()生成对应元组,转化为列表后生成字典。再对字典进行map操作,即可实现数值化。
df2 =DataFrame({'aa':['a','b','c'],'dd':['d','e','f']})
unique_value =list(enumerate(np.unique(df2.aa)))
print'unique_value:',unique_value
"""
unique_value: [(0, 'a'), (1, 'b'), (2, 'c')]
"""
dict = {key:value forvalue,key in unique_value}
for i in dict.keys():
print i,':',dict[i]
"""
a : 0
c : 2
b : 1
"""
df2.aa = df2.aa.map(lambdax:dict[x]).astype(int)
print df2
"""
aa dd
0 0 d
1 1 e
2 2 f
"""
- 哑变量
作用条件与枚举类似,属性值范围不大时,会为每一个值生成新的一列。结果需要concat
df =DataFrame({'column1':['aa','bb','cc'], 'column2':['dd','ee','ff']})
dummy_df_column1 =pd.get_dummies(df.column1)
print'dummy_df_column1:\n',dummy_df_column1
"""
dummy_df_column1:
aa bb cc
0 1 0 0
1 0 1 0
2 0 0 1
"""
dummy_df_column1 =dummy_df_column1.rename(columns=lambda x : 'dummy_'+str(x))
print 'dummy_df_column1:\n',dummy_df_column1
"""
dummy_df_column1:
dummy_aa dummy_bb dummy_cc
0 1 0 0
1 0 1 0
2 0 0 1
"""
df =pd.concat([df,dummy_df_column1],axis=1)
print df
"""
column1column2 dummy_aa dummy_bb dummy_cc
0 aa dd 1 0 0
1 bb ee 0 1 0
2 cc ff 0 0 1
"""
每个属性值对应一列,所以属性值很多的情况下不适用,会生成较大的df。将哑变量变换后的新的属性列直接concat到原来的df中即可。
- loc()
loc()对应列选取多行,第一个元素取行,第二个元素对应列,默认情况下为所有列
df =DataFrame({'a':[1,2,3,4],'b':[5,6,7,8]})
print df.loc[(df.a.values> 2)] #取出a列中值大于2的所有列的值,原df的值不变
"""
a b
2 3 7
3 4 8
"""
print df.loc[(df.a.values> 2),'a'] #只作用于a列,输出a列
"""
2 3
3 4
Name: a, dtype: int64
"""
df.loc[(df.a.values >2),'a'] = 2 #对其赋值,则改变df的值
print 'df = \n',df
"""
df =
a b
0 1 5
1 2 6
2 2 7
3 2 8
"""
- bining面元组合
主要用于产生一个有序分类
df =DataFrame(np.arange(16).reshape(8,2),columns=['aa','bb'])
print df
"""
aa bb
0 0 1
1 2 3
2 4 5
3 6 7
4 8 9
5 10 11
6 12 13
7 14 15
"""
先用pd.qcut()将数据分为若干份,对应新的一列,元素为一个范围字符串,仍然需要量化
df['cc'] = pd.qcut(df.aa,2) #cc加入到原df中,不需要concat
print df.cc
"""
0 [0, 7]
1 [0, 7]
2 [0, 7]
3 [0, 7]
4 (7, 14]
5 (7, 14]
6 (7, 14]
7 (7, 14]
Name: aa, dtype: category
Categories (2, object): [[0, 7] < (7, 14]]
"""
print pd.qcut(df.bb,4)
"""
0 [1,4.5]
1 [1,4.5]
2 (4.5,8]
3 (4.5,8]
4 (8,11.5]
5 (8,11.5]
6 (11.5,15]
7 (11.5,15]
Name: bb, dtype: category
Categories (4, object): [[1, 4.5] < (4.5, 8]< (8, 11.5] < (11.5, 15]]
"""
此处是均等分为2份或4份,实际数据中当数值并非均匀分布时,生成的bining应该不是均匀分布
还有就是貌似qcut几份有最大值限制,我实验的时候貌似最大只能分到9,配置为10则出错。想到分太多维太占用内存,这点也可以理解了。
df['dd'] = pd.qcut(df.bb,2)
print df
"""
aa bb cc dd
0 0 1 [0, 7] [1, 8]
1 2 3 [0, 7] [1, 8]
2 4 5 [0, 7] [1, 8]
3 6 7 [0, 7] [1, 8]
4 8 9 (7,14] (8, 15]
5 10 11 (7,14] (8, 15]
6 12 13 (7,14] (8, 15]
7 14 15 (7,14] (8, 15]
"""
有个奇怪的现象,此处如果df['cc'],df['dd']则列'cc','dd'加入到df中,如果df.cc,df.dd则没有加入df,需要concat
如果DataFrame对列的引用两种方式相同,为什么要有这种区别?
分类后元素只是string,还要进行数字化,可以采用enumerate,dummy,factorize。dummy_df =pd.get_dummies(df.cc).rename(columns=lambda x:'dummy_' + str(x) )
df =pd.concat([df,dummy_df],axis=1).drop(['cc','dd'],axis=1)
print df
"""
aa bb dummy_[0, 7] dummy_(7, 14]
0 0 1 1 0
1 2 3 1 0
2 4 5 1 0
3 6 7 1 0
4 8 9 0 1
5 10 11 0 1
6 12 13 0 1
7 14 15 0 1
"""
"""
这部分没玩起来,不知道怎么回事啊 ???
cc_enumerate = list(enumerate(np.unique(df.cc)))
cc_dict = {key:value for value,key in cc_enumerate}
for key in cc_dict.keys():
printkey,':',cc_dict[key]
printtype(key)
df['cc'] = df.cc.map(lambdax:cc_dict[x]).astype(int)
#print df.cc
"""
- factorize()
df =DataFrame({'column1':['a','b','a'],'column2':['e','f','g']})
df.column1 =pd.factorize(df.column1)[0]
df.column2 =pd.factorize(df.column2)[0]
print df
"""
column1 column2
0 0 0
1 1 1
2 0 2
"""
实验的时候对同一属性做dummy以及factorize数字化时,貌似dummy效果会好一点。???
- scaler
规范化,把数据压缩到一个范围,具体应用场景,不清楚
df =DataFrame({'aa':[5,10,15,20],'bb':[0,3,6,9],'cc':[1000,0,500,50],'dd':[1,100,3,2]})
scaler =preprocessing.StandardScaler()
df.aa = scaler.fit_transform(df.aa)
df.bb =scaler.fit_transform(df.bb)
df.cc =scaler.fit_transform(df.cc)
df.dd =scaler.fit_transform(df.dd)
print df
"""
aa bb cc dd
0 -1.341641 -1.341641 1.517239 -0.600832
1 -0.447214 -0.447214 -0.959886 1.731810
2 0.447214 0.447214 0.278677 -0.553708
3 1.341641 1.341641 -0.836030-0.577270
"""
还有很多对数据预处理的操作,missing值的操作,属性值的特性分析,特征提取等等。
当对数据进行离散化时,一个小结就是:
- 属性集可以分为2种类型:Quantitative(定量) and Qualitative(定性)。 定量是指可以按照某种规则进行排序,一般指数字类,例如年龄、工资等。 定性不容易排序,一般指字符串或数字与字符串的组合,如姓名等。
- 定量数据转换:scale以及bining
- scaling:数据缩放,当属性值范围较大时,可以将其按照比例进行缩小,范围可以从0-1,-1-1,具体如何设置范围,不清楚。基于神经网络算法,或者对基于距离的分类或聚类有效。对基于相似度而不是距离的算法,如随机森林,效果不一定好
- bining:面元组合,产生一个有序的分类值,例如年龄,工资等。调用pandas.qcut(),利用分位数对整个数值范围划分为几个bin,实验过程中,貌似有个最大bin数,9,当配置大于9时即出错。所以应该还是适用于范围并非太大的属性集。分类后产生的bin列,元素为string范围值,可通过哑变量、枚举或factorize进行数值化。
3.定性数据转换:枚举、哑变量、因子分解
- 枚举enumerate与因式分解factorize感觉差不多,都是将该列相同元素映射为一个数值。数值范围为连续自然数
- 哑变量dummy,单独为不同元素生成一列值,用0,1表示,主要用于标称属性或二元属性
- 当属性值范围较多时,哑变量会占用太大内存。另外使用随机森林生成feature_importance时,哑变量的列向量会分化了该属性的重要性,效果不如factorize好啊。