热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python中的功能管道,如R'sdplyr中的%>%

如何解决《python中的功能管道,如R'sdplyr中的%>%》经验,为你挑选了9个好方法。

在R(感谢magritrr)中,您现在可以通过更多功能管道语法执行操作%>%.这意味着不是编码:

> as.Date("2014-01-01")
> as.character((sqrt(12)^2)

你也可以这样做:

> "2014-01-01" %>% as.Date 
> 12 %>% sqrt %>% .^2 %>% as.character

对我来说,这更具可读性,这扩展到数据框之外的用例.python语言是否支持类似的东西?



1> Dunes..:

一种可能的方法是使用一个名为的模块macropy.Macropy允许您将转换应用于您编写的代码.因此a | b可以转化为b(a).这具有许多优点和缺点.

与Sylvain Leroux提到的解决方案相比,主要优点是您不需要为您感兴趣的函数创建中缀对象 - 只需标记您打算使用转换的代码区域.其次,由于转换是在编译时而不是运行时应用的,因此转换后的代码在运行时不会产生任何开销 - 所有工作都是在首次从源代码生成字节代码时完成的.

主要的缺点是,macropy需要激活某种方式才能使其工作(稍后提到).与更快的运行时相比,源代码的解析在计算上更复杂,因此程序将花费更长的时间来启动.最后,它添加了一种语法风格,这意味着不熟悉macropy的程序员可能会发现您的代码难以理解.

示例代码:

run.py

import macropy.activate 
# Activates macropy, modules using macropy cannot be imported before this statement
# in the program.
import target
# import the module using macropy

target.py

from fpipe import macros, fpipe
from macropy.quick_lambda import macros, f
# The `from module import macros, ...` must be used for macropy to know which 
# macros it should apply to your code.
# Here two macros have been imported `fpipe`, which does what you want
# and `f` which provides a quicker way to write lambdas.

from math import sqrt

# Using the fpipe macro in a single expression.
# The code between the square braces is interpreted as - str(sqrt(12))
print fpipe[12 | sqrt | str] # prints 3.46410161514

# using a decorator
# All code within the function is examined for `x | y` constructs.
x = 1 # global variable
@fpipe
def sum_range_then_square():
    "expected value (1 + 2 + 3)**2 -> 36"
    y = 4 # local variable
    return range(x, y) | sum | f[_**2]
    # `f[_**2]` is macropy syntax for -- `lambda x: x**2`, which would also work here

print sum_range_then_square() # prints 36

# using a with block.
# same as a decorator, but for limited blocks.
with fpipe:
    print range(4) | sum # prints 6
    print 'a b c' | f[_.split()] # prints ['a', 'b', 'c']

最后是努力工作的模块.我将其称为fpipe for function pipe作为其模拟shell语法,用于将输出从一个进程传递到另一个进程.

fpipe.py

from macropy.core.macros import *
from macropy.core.quotes import macros, q, ast

macros = Macros()

@macros.decorator
@macros.block
@macros.expr
def fpipe(tree, **kw):

    @Walker
    def pipe_search(tree, stop, **kw):
        """Search code for bitwise or operators and transform `a | b` to `b(a)`."""
        if isinstance(tree, BinOp) and isinstance(tree.op, BitOr):
            operand = tree.left
            function = tree.right
            newtree = q[ast[function](ast[operand])]
            return newtree

    return pipe_search.recurse(tree)


听起来不错,但我认为它只适用于Python 2.7(而不是Python 3.4).
我创建了一个没有依赖项的较小的库,该库的作用与@fpipe装饰器相同,但重新定义了右移(>>)而不是or(|):https://pypi.org/project/pipeop/

2> shadowtalker..:

管道是Pandas 0.16.2中的新功能.

例:

import pandas as pd
from sklearn.datasets import load_iris

x = load_iris()
x = pd.DataFrame(x.data, columns=x.feature_names)

def remove_units(df):
    df.columns = pd.Index(map(lambda x: x.replace(" (cm)", ""), df.columns))
    return df

def length_times_width(df):
    df['sepal length*width'] = df['sepal length'] * df['sepal width']
    df['petal length*width'] = df['petal length'] * df['petal width']

x.pipe(remove_units).pipe(length_times_width)
x

注意:Pandas版本保留了Python的引用语义.这就是为什么length_times_width不需要返回值; 它修改x到位.


遗憾的是,这仅适用于数据帧,因此我无法将其指定为正确的答案.但很高兴在这里提到我想到的主要用例是将其应用于数据帧.

3> Sylvain Lero..:

python语言是否支持类似的东西?

"更多功能管道语法"这真的是一个更"功能"的语法吗?我会说它为R添加了一个"中缀"语法.

话虽这么说,Python的语法并没有直接支持标准运算符之外的中缀表示法.


如果你真的需要这样的东西,你应该从Tomer Filiba那里获取代码作为实现你自己的中缀表示法的起点:

代码示例和评论由Tomer Filiba(http://tomerfiliba.com/blog/Infix-Operators/):

from functools import partial

class Infix(object):
    def __init__(self, func):
        self.func = func
    def __or__(self, other):
        return self.func(other)
    def __ror__(self, other):
        return Infix(partial(self.func, other))
    def __call__(self, v1, v2):
        return self.func(v1, v2)

使用这个特殊类的实例,我们现在可以使用一个新的"语法"来调用函数作为中缀运算符:

>>> @Infix
... def add(x, y):
...     return x + y
...
>>> 5 |add| 6



4> smci..:

PyToolz [doc]允许任意组合管道,只是它们没有用管道操作符语法定义.

请按照上面的链接进行快速入门.这是一个视频教程:http: //pyvideo.org/video/2858/functional-programming-in-python-with-pytoolz

In [1]: from toolz import pipe

In [2]: from math import sqrt

In [3]: pipe(12, sqrt, str)
Out[3]: '3.4641016151377544'



5> shadowtalker..:

如果您只想将其用于个人脚本,您可能需要考虑使用Coconut而不是Python.

椰子是Python的超集.因此,您可以使用Coconut的管道操作员|>,同时完全忽略椰子语言的其余部分.

例如:

def addone(x):
    x + 1

3 |> addone

编译成

# lots of auto-generated header junk

# Compiled Coconut: -----------------------------------------------------------

def addone(x):
    return x + 1

(addone)(3)



6> Robin Hillia..:

我错过了|>Elixir 的管道操作符,所以我创建了一个简单的函数装饰器(大约50行代码),>>在编译时使用ast库和compile/exec 将Python右移操作符重新解释为类似Elixir的管道:

from pipeop import pipes

def add3(a, b, c):
    return a + b + c

def times(a, b):
    return a * b

@pipes
def calc()
    print 1 >> add3(2, 3) >> times(4)  # prints 24

它所做的只是重写a >> b(...)b(a, ...).

https://pypi.org/project/pipeop/

https://github.com/robinhilliard/pipes



7> mhsekhavat..:

您可以使用sspipe库。它暴露了两个对象ppx。类似于x %>% f(y,z),您可以写作,x | p(f, y, z)并且类似于x %>% .^2您可以写作x | px**2

from sspipe import p, px
from math import sqrt

12 | p(sqrt) | px ** 2 | p(str)



8> yardsale8..:

建筑pipeInfix

正如Sylvain Leroux所暗示,我们可以使用Infix运算符来构造中缀pipe.让我们看看这是如何实现的.

首先,这是Tomer Filiba的代码

代码示例和评论由Tomer Filiba(http://tomerfiliba.com/blog/Infix-Operators/):

from functools import partial

class Infix(object):
    def __init__(self, func):
        self.func = func
    def __or__(self, other):
        return self.func(other)
    def __ror__(self, other):
        return Infix(partial(self.func, other))
    def __call__(self, v1, v2):
        return self.func(v1, v2)

使用这个特殊类的实例,我们现在可以使用一个新的"语法"来调用函数作为中缀运算符:

>>> @Infix
... def add(x, y):
...     return x + y
...
>>> 5 |add| 6

管道运算符将前一个对象作为参数传递给管道后面的对象,因此x %>% f可以转换为f(x).因此,pipe可以使用Infix如下定义运算符:

In [1]: @Infix
   ...: def pipe(x, f):
   ...:     return f(x)
   ...:
   ...:

In [2]: from math import sqrt

In [3]: 12 |pipe| sqrt |pipe| str
Out[3]: '3.4641016151377544'

关于部分申请的说明

%>%从运营商dpylr通过在函数的第一个参数推参数,所以

df %>% 
filter(x >= 2) %>%
mutate(y = 2*x)

对应于

df1 <- filter(df, x >= 2)
df2 <- mutate(df1, y = 2*x)

在Python中实现类似功能的最简单方法是使用currying.该toolz库提供了一个curry装饰器功能,可以轻松构建curry函数.

In [2]: from toolz import curry

In [3]: from datetime import datetime

In [4]: @curry
    def asDate(format, date_string):
        return datetime.strptime(date_string, format)
    ...:
    ...:

In [5]: "2014-01-01" |pipe| asDate("%Y-%m-%d")
Out[5]: datetime.datetime(2014, 1, 1, 0, 0)

请注意,|pipe|将参数推送到最后一个参数位置,即

x |pipe| f(2)

对应于

f(2, x)

在设计curried函数时,应该在参数列表的前面放置静态参数(即可能用于许多示例的参数).

请注意,toolz其中包括许多预先计算的功能,包括operator模块中的各种功能.

In [11]: from toolz.curried import map

In [12]: from toolz.curried.operator import add

In [13]: range(5) |pipe| map(add(2)) |pipe| list
Out[13]: [2, 3, 4, 5, 6]

其大致对应于R中的以下内容

> library(dplyr)
> add2 <- function(x) {x + 2}
> 0:4 %>% sapply(add2)
[1] 2 3 4 5 6

使用其他中缀分隔符

您可以通过覆盖其他Python运算符方法来更改围绕Infix调用的符号.例如,交换__or____ror____mod____rmod__将改变|操作者的mod操作者.

In [5]: 12 %pipe% sqrt %pipe% str
Out[5]: '3.4641016151377544'



9> Eli Korvigo..:

添加我的2c.我个人使用package fn进行功能样式编程.你的例子转化为

from fn import F, _
from math import sqrt

(F(sqrt) >> _**2 >> str)(12)

F是一个包装类,具有功能风格的语法糖,用于部分应用和组合._是一个用于匿名函数的Scala样式构造函数(类似于Python lambda); 它表示一个变量,因此您可以_在一个表达式中组合多个对象以获得具有更多参数的函数(例如_ + _,相当于lambda a, b: a + b).F(sqrt) >> _**2 >> str导致一个Callable对象可以根据需要多次使用.


推荐阅读
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文介绍了在安装或运行 Python 项目时遇到的 'ModuleNotFoundError: No module named setuptools_rust' 错误,并提供了解决方案。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 尽管使用TensorFlow和PyTorch等成熟框架可以显著降低实现递归神经网络(RNN)的门槛,但对于初学者来说,理解其底层原理至关重要。本文将引导您使用NumPy从头构建一个用于自然语言处理(NLP)的RNN模型。 ... [详细]
author-avatar
广药中山校区艺术团啦啦队
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有