上文交代了一些啰嗦事,本文开始,就要来点实际的了。html
先来一个比较简单的场景:python
Given:一个包括N(极其复杂,这里取3个)个列的DataFrame:df,df包括index;算法
And:对df全部列元素进行一些处理,获得df的一个变换后的df_new;app
And:对df_new的某些列作极其复杂的判断,获得新的列result;机器学习
When:须要将要根据result对df进行分析;函数
Then:将result追加到df中。学习
上述的场景是个人一个算法验证的场景,简单地说,就是须要经过对原始数据进行变换,而后获得新的列,而后追加到原始数据中,最后进行分析。spa
首先构造一下模拟的数据吧。咱们的数据经过随机数产生,为10*3的数据,每一列的名称为A/B/C,放到csv格式的文件中,文件内容以下所示:code
A,B,C 4.556325895482557,4.9467487190814206,9.240498646959768 6.798122785026925,9.205498509979439,6.495701755638054 1.7088666262153485,1.9490481646738644,5.016719349132167 7.68793618140002,4.288529993589748,0.4479283787649413 0.22238136867848257,2.861119654701667,5.296500633944277 3.8352546975711,0.29287579880826087,1.0438719791356377 4.603712955967749,5.647815101448938,0.6054047619225811 6.916870514198006,8.903690009637602,4.836793019361064 9.845396552800361,0.8159084013183737,0.8425827491512894 2.425545747141858,7.353661205806686,2.982326067390466
通常字符型的文件会以上述的逗号隔开的方式存储,经过pandas的read_csv()能够方便的读入数据到DataFrame,以下代码所示:htm
import pandas as pd import numpy as np df = pd.read_csv('d:/data.csv')
pd.read_csv()默认的读法就是上述代码那样,他会将第一行当作列名读入。假如咱们的csv数据中不包含列名,能够经过header=None来禁止将第一行当作列名;假如csv数据中没有列名,而咱们想要指定列名,这也是我常常作的,能够经过name=[]参数,经过一个列表指定全部列的名称。指定列名有一个好处就是列名能够当作DataFrame的属性,对列进行访问,后续会介绍。
读进来的输入以下所示:
而后,咱们须要对df进行变换。
这里模拟一种变换,就是将每一列进行均值位0,方差为1的变换,代码以下:
import pandas as pd import numpy as np df = pd.read_csv('d:/data.csv') df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std()) df_new
其中,df.apply()函数是df的一个函数式接口,表示依次对df的列(A/B/C)进行迭代,其参数为一个lambda表达式,lambda的参数col就表示df的一个列。
col实际上是Series的一个对象,其中包含大量的数据处理方法,这里实用的是其中两个:均值mean()和std()方差。
lambda的实现部分使用了Pandas的向量化的运算方式,也就是说col虽然是一个Series,可是咱们对其操做就像操做一个标量同样,可是自动传播给全部的元素。
通过上述代码的运算,每一列都被映射到新的df_new中,这个方式在机器学习、数据挖掘中很常见。结果以下图所示。
A | B | C | |
---|---|---|---|
0 | -0.102247 | 0.100417 | 1.865099 |
1 | 0.652462 | 1.435738 | 0.944303 |
2 | -1.060854 | -0.839506 | 0.448149 |
3 | 0.952021 | -0.105966 | -1.084541 |
4 | -1.561285 | -0.553528 | 0.542008 |
5 | -0.344998 | -1.358795 | -0.884620 |
6 | -0.086294 | 0.320234 | -1.031713 |
7 | 0.692439 | 1.341107 | 0.387790 |
8 | 1.678338 | -1.194799 | -0.952147 |
9 | -0.819582 | 0.855099 | -0.234328 |
如今,咱们要使用df_new的数据计算咱们的结果了。若是逻辑很简单,则能够直接经过Pandas的IF THEN逻辑实现,复杂的算法能够须要本身一行一行的遍历df_new,经过if else逻辑实现。咱们先说一个简单的状况。
假如,咱们的算法是这样的:若是A>0.5而且B<0.5,则为True,不然若是C>0.5,则为True,则否为False,实现代码以下所示:
import pandas as pd import numpy as np df = pd.read_csv('d:/data.csv') df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std()) df_new.ix[(df_new.A > 0.5) & (df_new.B < 0.5), 'Result'] = True df_new.ix[~((df_new.A > 0.5) & (df_new.B < 0.5)) & (df_new.C > 0.5), 'Result'] = True df_new.ix[~(~((df_new.A > 0.5) & (df_new.B < 0.5)) & (df_new.C > 0.5)), 'Result'] = False df_new
结果以下所示:
因为算法逻辑不是很复杂,抽象起来也就三个状况,因此经过Pandas的IF Then的机制实现了Result列的添加。
DataFrame.ix[condition, 'newOrExistsColname'] = value,具体能够参考Pandas的十分钟入门教程,开始就是讲这个的。
须要强调的是咱们经过df_new.A这样的方式访问A列元素,这是Pandas的方便之处;而且各类比较和& ~操做都是针对元素的;而且只有index相同的元素才会比较,并且Result也是添加到对应的index列的。
假如算法实如今太复杂,不是简单的集中状况能够讲清楚的,这个时候我采用的方法就是C++和Java中最常使用的for循环了,几乎万能。还以上述的算法为例,代码以下:
import pandas as pd import numpy as np df = pd.read_csv('d:/data.csv') df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std()) result = pd.Series([False]*len(df_new)) for i in range(len(df_new)): item = df_new.iloc[i, :] if item.A > 0.5 and item.B < 0.5: result[i] = True elif item.C > 0.5: result[i] = True else: result[i] = False # unnecessary df_new['Result'] = result df_new
代码中一片浓郁的C、Java风格,虽然不那么函数式也不向量化,可是我就是感受熟悉,毕竟我最先学习的是C。
首先,我定义了一个Series,初始化为False,而后经过一个for循环,遍历df_new的全部行,依次为result赋值,最后,经过df_new['newcolname']=的方式将resut追加到df_new中了。
注意,当将Series往DataFrame或者Series中拼接的时候,默认的都是安装index对齐的,也就是行的index一致的才会拼接到一块儿,而与行的顺序无关,这点是Pandas的强大之处(数据的自动对齐,在groupby以后的数据中特别有用),千万别忽视了这点。
最后,咱们要将df_new.Result追加给df,由于df_new.Result本质上仍是一个Series,因此上述的代码中已经有了一种方式:df.ix['Result']=df_new.Result。
代码以下:
import pandas as pd import numpy as np df = pd.read_csv('d:/data.csv') df_new = df.apply(lambda col: (col - col.mean()) * 1.0 / col.std()) result = pd.Series([False]*len(df_new)) for i in range(len(df_new)): item = df_new.iloc[i, :] if item.A > 0.5 and item.B < 0.5: result[i] = True elif item.C > 0.5: result[i] = True else: result[i] = False # unnecessary df_new['Result'] = result df['Result'] = df_new.Result df
最终结果以下:
本文要点:
Pandas读取CSV文件方法;
Pandas的追加新列方法:df.ix[condition, 'newcolname'] = value(标量或者向量) 或者 df['newcolname'] = value(标量或者向量);
Pandas的df.apply()对列进行迭代的方法;
Pandas的df中的一些经常使用的数据处理方法;
Pandas的Series的简单逻辑操做& | ~;
看,是否是很简单。
未完待续……