快捷搜索:  汽车  科技

python数据分析使用的第三方类库(用tidyverse的方式玩转)

python数据分析使用的第三方类库(用tidyverse的方式玩转)In [7]: df >> define(z=if_else('x > 1' 1 0)) Out[7]: x y z 0 0 zero 0 1 1 one 0 2 2 two 1 3 3 three 1 与 R 中使用 tidyverse 包中的函数类似,也可以将数据框作为函数的第一个参数In [5]: df Out[5]: x y 0 0 zero 1 1 one 2 2 two 3 3 three In [6]: df >> define(z='x') Out[6]: x y z 0 0 zero 0 1 1 one 1 2 2 two 2 3 3 three 3 使用 if_

前言

今天,我们要介绍一个用于数据操作的 Python 第三方库 —— plydata,这个库是基于 R 中的 dplyr、tidyr 和 forcats 包,许多函数名称都是直接借用过来的

plydata 使用 >> 作为管道操作符,用于替代 ply(data *verbs) 函数,目前只支持 pandas 的 DataFrame 数据结构,后续可能还会添加对数据库的支持

下面我们来看看怎么使用 plydata 来玩转数据操作吧

使用

首先,使用 pip 进行安装

pip install plydata

我们先举个简单的例子,先导入对应的模块

import numpy as np import pandas as pd from plydata import define query if_else ply

创建一个 DataFrame

df = pd.DataFrame({ 'x': [0 1 2 3] 'y': ['zero' 'one' 'two' 'three']} )

使用 define 函数为数据框添加一列(或者使用 mutate 函数,两者相同,对应于 tidyverse 中的同名函数)

In [5]: df Out[5]: x y 0 0 zero 1 1 one 2 2 two 3 3 three In [6]: df >> define(z='x') Out[6]: x y z 0 0 zero 0 1 1 one 1 2 2 two 2 3 3 three 3

使用 if_else 来添加不同的值

In [7]: df >> define(z=if_else('x > 1' 1 0)) Out[7]: x y z 0 0 zero 0 1 1 one 0 2 2 two 1 3 3 three 1

与 R 中使用 tidyverse 包中的函数类似,也可以将数据框作为函数的第一个参数

In [8]: query(df 'x > 1') Out[8]: x y 2 2 two 3 3 three # 等同于下面的操作 In [9]: df >> query('x > 1') Out[9]: x y 2 2 two 3 3 three

或者使用 ply 函数代替管道操作,例如

In [10]: ply(df ...: define(z=if_else('x > 1' 1 0)) ...: query('z == 1') ...: ) Out[10]: x y z 2 2 two 1 3 3 three 1

将每一次的操作作为参数,传递给 ply 函数

如果与 plotnine(基于 ggplot2 的 Python 实现)联用,可以很容易将 R 的绘图代码,转换为 Python。

例如,对于如下 R 代码,绘制 sin(x) 函数在 [0 2] 区间的图形

library(tidyverse) tibble(x = seq(0 2*pi length.out = 500)) %>% mutate(y = sin(x) sign = if_else(y >= 0 "positive" "negative")) %>% ggplot(aes(x y)) geom_line(aes(colour = sign) size = 1.5)

python数据分析使用的第三方类库(用tidyverse的方式玩转)(1)

转换为 Python 代码

from plotnine import ggplot aes geom_line ( pd.DataFrame({'x': np.linspace(0 2*np.pi 500)}) >> define(y='np.sin(x)') >> define(sign=if_else('y >= 0' '"positive"' '"negative"')) >> (ggplot(aes('x' 'y')) geom_line(aes(color='sign') size=1.5)) )

python数据分析使用的第三方类库(用tidyverse的方式玩转)(2)

注意:在 Python 中,运算表达式都放置在引号内部,且字符串要表示为嵌套的引号

使用 call 函数为数据框执行外部函数或 pd.DataFrame 函数,例如,应用外部函数

In [11]: df = pd.DataFrame({ ...: 'A': {0: 'a' 1: 'b' 2: 'c'} ...: 'B': {0: 1 1: 3 2: 5} ...: 'C': {0: 2 1: 4 2: np.nan} ...: }) In [12]: df >> call(pd.melt) Out[12]: variable value 0 A a 1 A b 2 A c 3 B 1 4 B 3 5 B 5 6 C 2.0 7 C 4.0 8 C NaN In [13]: df >> call(pd.melt id_vars=['A'] value_vars=['B']) Out[13]: A variable value 0 a B 1 1 b B 3 2 c B 5

应用对象方法

In [14]: df >> call('.dropna' axis=1) Out[14]: A B 0 a 1 1 b 3 2 c 5 In [15]: (df ...: >> call(pd.melt) ...: >> query('variable != "B"') ...: >> call('.reset_index' drop=True) ...: ) Out[15]: variable value 0 A a 1 A b 2 A c 3 C 2.0 4 C 4.0 5 C NaN 示例1. 单表操作

单表操作主要包括如下函数

python数据分析使用的第三方类库(用tidyverse的方式玩转)(3)

其功能都与 dplyr 包中的同名函数一样

例如,mutate 函数添加列

In [16]: df >> mutate(x_sq = 'x**2') Out[16]: x x_sq 0 1 1 1 2 4 2 3 9 In [17]: df >> mutate(('x*2' 'x*2') ('x*3' 'x*3') x_cubed='x**3') Out[17]: x x*2 x*3 x_cubed 0 1 2 3 1 1 2 4 6 8 2 3 6 9 27

使用 arrange 函数对数据框进行排序

In [18]: df = pd.DataFrame({'x': [1 5 2 2 4 0] ...: 'y': [1 2 3 4 5 6]}) In [19]: df >> arrange('x') Out[19]: x y 5 0 6 0 1 1 2 2 3 3 2 4 4 4 5 1 5 2 In [20]: df >> arrange('x' '-y') Out[20]: x y 5 0 6 0 1 1 3 2 4 2 2 3 4 4 5 1 5 2 In [21]: df >> arrange('np.sin(y)') Out[21]: x y 4 4 5 3 2 4 5 0 6 2 2 3 0 1 1 1 5 2

使用 group_by 进行分组

In [22]: df = pd.DataFrame({'x': [1 5 2 2 4 0 4] ...: 'y': [1 2 3 4 5 6 5]}) In [23]: df >> group_by('x') Out[23]: groups: ['x'] x y 0 1 1 1 5 2 2 2 3 3 2 4 4 4 5 5 0 6 6 4 5 In [24]: df >> group_by('x') >> group_indices() Out[24]: array([1 4 2 2 3 0 3])

类似于 define,group_by 可以添加新列

In [25]: df >> group_by('y-1' xplus1='x 1') Out[25]: groups: ['y-1' 'xplus1'] x y y-1 xplus1 0 1 1 0 2 1 5 2 1 6 2 2 3 2 3 3 2 4 3 3 4 4 5 4 5 5 0 6 5 1 6 4 5 4 5

如果后续的动词未使用分组信息,则新产生的列将会保留在数据框中

In [26]: df >> group_by('y-1' xplus1='x 1') >> select('y') Out[26]: groups: ['y-1' 'xplus1'] y-1 xplus1 y 0 0 2 1 1 1 6 2 2 2 3 3 3 3 3 4 4 4 5 5 5 5 1 6 6 4 5 5

使用 query 来进行行过滤

In [27]: df = pd.DataFrame({'x': [0 1 2 3 4 5] ...: 'y': [0 0 1 1 2 3]}) In [28]: df >> query('x % 2 == 0') Out[28]: x y 0 0 0 2 2 1 4 4 2 In [29]: df >> query('x % 2 == 0 and y > 0') Out[29]: x y 2 2 1 4 4 2 In [30]: df >> query('x % 2 == 0 & y > 0') Out[30]: x y 2 2 1 4 4 2 In [31]: df >> group_by('y') >> query('x == x.min()') Out[31]: groups: ['y'] x y 0 0 0 2 2 1 4 4 2 5 5 3

使用 summarize 函数对数据进行统计

In [32]: df = pd.DataFrame({'x': [1 5 2 2 4 0 4] ...: 'y': [1 2 3 4 5 6 5] ...: 'z': [1 3 3 4 5 5 5]}) In [33]: df >> summarize('np.sum(x)' max='np.max(x)') Out[33]: np.sum(x) max 0 18 5 In [34]: df >> group_by('y' 'z') >> summarize(mean_x='np.mean(x)') Out[34]: y z mean_x 0 1 1 1.0 1 2 3 5.0 2 3 3 2.0 3 4 4 2.0 4 5 5 4.0 5 6 5 0.0

支持如下函数:

  • min(x) - numpy.amin() 的别名
  • max(x) - numpy.amax() 的别名
  • sum(x) - numpy.sum() 的别名
  • cumsum(x) - numpy.cumsum() 的别名
  • mean(x) - numpy.mean() 的别名
  • median(x) - numpy.median() 的别名
  • std(x) - numpy.std() 的别名
  • first(x) - x 的第一个元素
  • last(x) - x 的最后一个元素
  • nth(x n) - x 的第 n 个值或 numpy.nan
  • n_distinct(x) - x 中唯一值的个数
  • n_unique(x) - n_distinct 的别名
  • n() - 当前分组的个数

In [35]: df >> summarize('min(x)' 'max(x)' 'mean(x)' 'sum(x)' ...: 'first(x)' 'last(x)' 'nth(x 3)') Out[35]: min(x) max(x) mean(x) sum(x) first(x) last(x) nth(x 3) 0 0 5 2.571429 18 1 4 2

分组求值

In [36]: df >> group_by('y') >> summarize(y_count='n()') Out[36]: y y_count 0 1 1 1 2 1 2 3 1 3 4 1 4 5 2 5 6 1 In [37]: df >> group_by('y') >> summarize('mean(x)') Out[37]: y mean(x) 0 1 1.0 1 2 5.0 2 3 2.0 3 4 2.0 4 5 4.0 5 6 0.0 2. 双表操作

双表操作主要包含:

python数据分析使用的第三方类库(用tidyverse的方式玩转)(4)

与 dplyr 同名函数执行相同的功能。例如

In [38]: df1 = pd.DataFrame({ ...: 'col1': ['one' 'two' 'three'] ...: 'col2': [1 2 3] ...: }) In [39]: df2 = pd.DataFrame({ ...: 'col1': ['one' 'four' 'three'] ...: 'col2': [1 4 3] ...: }) In [40]: anti_join(df1 df2 on='col1') Out[40]: col1 col2 1 two 2 In [41]: outer_join(df1 df2 on='col1') Out[41]: col1 col2_x col2_y 0 one 1.0 1.0 1 two 2.0 NaN 2 three 3.0 3.0 3 four NaN 4.0 In [42]: inner_join(df1 df2 on='col1') Out[42]: col1 col2_x col2_y 0 one 1 1 1 three 3 3 In [43]: left_join(df1 df2 on='col1') Out[43]: col1 col2_x col2_y 0 one 1 1.0 1 two 2 NaN 2 three 3 3.0 In [44]: right_join(df1 df2 on='col1') Out[44]: col1 col2_x col2_y 0 one 1.0 1 1 four NaN 4 2 three 3.0 3 In [45]: semi_join(df1 df2 on='col1') Out[45]: col1 col2 0 one 1 2 three 3 3. Tidy Verbs3.1 数据透视表

  1. gather

In [48]: from plydata.tidy import * In [49]: df = pd.DataFrame({ ...: 'name': ['mary' 'oscar' 'martha' 'john'] ...: 'math': [92 83 85 90] ...: 'art': [75 95 80 72] ...: }) In [50]: df >> gather('subject' 'grade' ['math' 'art']) Out[50]: name subject grade 0 mary math 92 1 oscar math 83 2 martha math 85 3 john math 90 4 mary art 75 5 oscar art 95 6 martha art 80 7 john art 72

  1. pivot_longer

In [51]: df = pd.DataFrame({ ...: 'name': ['mary' 'mary' 'john' 'john'] ...: 'city':['dakar' 'dakar' 'lome' 'lome'] ...: 'year': [1990 1992 1996 1998] ...: 'data_t1_sunny': [8 6 4 7] ...: 'data_t2_rainy': [9 7 7 6] ...: }) In [52]: df >> pivot_longer( ...: cols=select(startswith='data') ...: names_to=['take' 'season'] ...: values_to='score' ...: names_pattern=r'data_(t\d)(_\w )' ...: names_prefix={'take': 't' 'season': '_'} ...: ) Out[52]: name city year take season score 0 mary dakar 1990 1 sunny 8 1 mary dakar 1992 1 sunny 6 2 john lome 1996 1 sunny 4 3 john lome 1998 1 sunny 7 4 mary dakar 1990 2 rainy 9 5 mary dakar 1992 2 rainy 7 6 john lome 1996 2 rainy 7 7 john lome 1998 2 rainy 6

  1. pivot_wider

In [53]: df = pd.DataFrame({ ...: 'name': ['mary' 'oscar' 'martha' 'john'] * 2 ...: 'initials': ['M.K' 'O.S' 'M.J' 'J.T'] * 2 ...: 'subject': np.repeat(['math' 'art'] 4) ...: 'grade': [92 83 85 90 75 95 80 72] ...: 'midterm': [88 83 89 93 85 95 76 79] ...: }) In [54]: df >> pivot_wider( ...: names_from='subject' ...: values_from=('grade' 'midterm') ...: ) Out[54]: initials name grade_art grade_math midterm_art midterm_math 0 J.T john 72 90 79 93 1 M.J martha 80 85 76 89 2 M.K mary 75 92 85 88 3 O.S oscar 95 83 95 83

  1. spread

In [55]: df = pd.DataFrame({ ...: 'name': ['mary' 'oscar' 'martha' 'john'] * 2 ...: 'subject': np.repeat(['math' 'art'] 4) ...: 'grade': [92 83 85 90 75 95 80 72] ...: }) In [56]: df >> spread('subject' 'grade') Out[56]: name art math 0 john 72 90 1 martha 80 85 2 mary 75 92 3 oscar 95 83 3.2 字符串列

  1. extract:使用正则表达式分割字符串列
  2. separate:使用指定分隔符分割字符串列
  3. separate_rows:将一行变量的值分割为多行

In [57]: df = pd.DataFrame({ ...: 'parent': ['martha' 'james' 'alice'] ...: 'child': ['leah' 'joe vinny laura' 'pat lee'] ...: 'age': ['3' '12 6 4' '2 7'] ...: }) In [58]: df >> separate_rows('child' 'age') Out[58]: parent child age 0 martha leah 3 1 james joe 12 2 james vinny 6 3 james laura 4 4 alice pat 2 5 alice lee 7

  1. unite:将多列合并为一列
4. 总结

plydata 还提供了很多函数用于处理分类变量,我们就不再一一说明了,感兴趣的可以通过查阅下面的文档来学习,每个函数都有对应的例子,清晰易懂

https://plydata.readthedocs.io/en/stable/api.html

猜您喜欢: