在数据清洗层面,一般存在以下几个数据整形的需求:
1. 新建一个列,这个列是另外列的运算结果
2. 按照列进行分组统计结果
3. 选择符合条件的行/列
下面一一看看py和R的区别
1、进行新列的变换
这个R中很轻松,可以直接从数据框中导入数据进行处理,并且可以直接进行向量计算,比如想要iris的某一列求平方:
iris$Sepal.Length^2
就是一个新向量,当然可以把这个向量加到iris数据集中:
iris$power<-iris$Sepal.Length^2
在py中,和R还是比较类似,如果不加任何处理,直接就可以运算比如
iris['Sepal.Length']*2
iris['Sepal.Length']+1
然而有的时候会有稍微复杂的运算,这时候和R也比较类似,就会应用到apply函数(竟然和R的apply一样),在R中,比如我定义一个x^2-x的函数应用到列:
sapply(iris$Sepal.Length),function(x) x^2-x)
在py中,也是用apply函数遍历所有:
iris['Sepal.Length'].apply(lambda x:x**2-x)
其中的lambda函数就相当于一个简易的function(x)
2、分组汇总统计
分组汇总私下认为py比R能稍微简单一点,R中的函数倒是很多,aggregate/melt+reshape/ddply,还有我最喜欢用的data.table,顺便说一句data.table的思想和py groupby的思想基本一致。
在py中,分组后的agg函数(类似于R的aggregate)很常用,比如要按照Species分组汇总其他均值:
iris.groupby('Species')['Sepal.Length'].mean()
Species
setosa 5.006
versicolor 5.936
virginica 6.588
Name: Sepal.Length, dtype: float64
或者全部加总:
iris.groupby('Species').sum()
Sepal.Length Sepal.Width Petal.Length Petal.Width
Species
setosa 250.3 171.4 73.1 12.3
versicolor 296.8 138.5 213.0 66.3
virginica 329.4 148.7 277.6 101.3
可以看到,其实sum和mean等函数,都是一个典型的汇总函数,或者说是多对一,一般对这种函数有groupby的必要,否则都是一对一,可以直接向量计算。
当然groupby也可以自定义函数,先直接用var计算方差:
iris.groupby('Species').agg('var')
Sepal.Length Sepal.Width Petal.Length Petal.Width
Species
setosa 0.124249 0.143690 0.030159 0.011106
versicolor 0.266433 0.098469 0.220816 0.039106
virginica 0.404343 0.104004 0.304588 0.075433
根据方差定义,我们知道是针对权重下所有变量-期望然后求和:
iris.groupby('Species').agg(
lambda x:sum((x-x.mean())**2/len(x)))
代码如上,又用到了lambda,其中,**2两个乘法就是^2,次方,而mean()是个整合函数,len(x)相当于R的length也算是个整合函数,所以这个函数首先满足整合函数条件,再往下,这个函数的定义和方差一致,得出结果是:
iris.groupby('Species').agg(
lambda x:sum((x-x.mean())**2/len(x)))
Sepal.Length Sepal.Width Petal.Length Petal.Width
Species
setosa 0.121764 0.140816 0.029556 0.010884
versicolor 0.261104 0.096500 0.216400 0.038324
virginica 0.396256 0.101924 0.298496 0.073924
果然和直接用var求得结果一致。
3、选择符合条件的行列
R中一般会用subset进行筛选:
subset(iris,Species='setosa']
subset(iris,Sepal.Length<5]
确实比较方便,而py中也还可以,有用到了上一章的loc函数:
iris.loc[iris['Species']=='setosa']
比如选择Sepal.Length<5的:
iris.loc[iris['Sepal.Length']<5]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
6 4.6 3.4 1.4 0.3 setosa
8 4.4 2.9 1.4 0.2 setosa
9 4.9 3.1 1.5 0.1 setosa
11 4.8 3.4 1.6 0.2 setosa
12 4.8 3.0 1.4 0.1 setosa
13 4.3 3.0 1.1 0.1 setosa
22 4.6 3.6 1.0 0.2 setosa
24 4.8 3.4 1.9 0.2 setosa
29 4.7 3.2 1.6 0.2 setosa
30 4.8 3.1 1.6 0.2 setosa
34 4.9 3.1 1.5 0.2 setosa
37 4.9 3.6 1.4 0.1 setosa
38 4.4 3.0 1.3 0.2 setosa
41 4.5 2.3 1.3 0.3 setosa
42 4.4 3.2 1.3 0.2 setosa
45 4.8 3.0 1.4 0.3 setosa
47 4.6 3.2 1.4 0.2 setosa
57 4.9 2.4 3.3 1.0 versicolor
106 4.9 2.5 4.5 1.7 virginica
大致如此。
关于数据整形,是数据分析常用到不能再常用的技能,总的来说,这块py和R不分高下,但是个人对py类SQL的操作还是更上手点。