Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:如何使用apply广播操作而不编写辅助函数_Python_Numpy_Pandas_Apply - Fatal编程技术网

Python:如何使用apply广播操作而不编写辅助函数

Python:如何使用apply广播操作而不编写辅助函数,python,numpy,pandas,apply,Python,Numpy,Pandas,Apply,我有一列包含字符串的数据,我想创建一个新列,只从相应的数据字符串中获取前两个字符 为此使用apply函数似乎是合乎逻辑的,但它的工作方式与预期不同。它甚至似乎与apply的其他用法不一致。见下文 In [205]: dfrm_test = pandas.DataFrame({"A":np.repeat("the", 10)}) In [206]: dfrm_test Out[206]: A 0 the 1 the 2 the 3 the 4 the 5 the 6 th

我有一列包含字符串的数据,我想创建一个新列,只从相应的数据字符串中获取前两个字符

为此使用
apply
函数似乎是合乎逻辑的,但它的工作方式与预期不同。它甚至似乎与
apply
的其他用法不一致。见下文

In [205]: dfrm_test = pandas.DataFrame({"A":np.repeat("the", 10)})

In [206]: dfrm_test
Out[206]:
     A
0  the
1  the
2  the
3  the
4  the
5  the
6  the
7  the
8  the
9  the

In [207]: dfrm_test["A"].apply(lambda x: x+" cat")
Out[207]:
0    the cat
1    the cat
2    the cat
3    the cat
4    the cat
5    the cat
6    the cat
7    the cat
8    the cat
9    the cat
Name: A

In [208]: dfrm_test["A"].apply(lambda x: x[0:2])
Out[208]:
0    the
1    the
Name: A
基于此,
apply
似乎什么都不做,只执行与内部调用的NumPy等价的操作。也就是说,
apply
似乎执行与第一个示例中的
arr+“cat”
相同的操作。如果NumPy碰巧播出了这个节目,那么它就会起作用。如果不是,那就不会了

但这似乎违背了文件中的承诺。以下是pandas.Series.apply的预期报价:

对系列的值调用函数。可以是只需要单个值的ufunc或Python函数()

它明确表示它可以接受只需要单个值的Python函数。不起作用的函数(
lambda x:x[0:2]
)肯定满足这一点。它并没有说单个参数必须是数组。考虑到像
numpy.sqrt
这样的东西通常用于单输入(因此不完全是数组),因此期望Pandas使用任何这样的函数似乎是很自然的

是否有我在这里缺少的使用
apply
的方法

注意:我确实在下面编写了自己的额外函数:

def ix2(arr):
    return np.asarray([x[0:2] for x in arr])
我验证了这个版本是否可以与Pandas
apply
一起使用。但这与问题无关。编写外部操作在Series对象之上的东西要比不断编写使用列表理解的包装器来有效循环Series内容容易得多。这不正是
apply
应该从用户那里抽象出来的吗

我使用的是Pandas版本0.7.3,它位于工作场所共享网络上,因此无法升级到最新版本

添加:

我能够确认此行为从版本0.7.3更改为版本0.8.1。在0.8.1中,它在没有NumPy ufunc包装的情况下按预期工作

我的猜测是,在代码中,有人试图在try-except语句中使用
numpy.vectorize
numpy.fromfunc
。也许它不能正确地与我正在使用的特定lambda函数一起工作,因此在代码的
部分,它默认只依赖于通用NumPy广播


如果可能的话,从Pandas开发者那里得到一些确认将是非常棒的。但与此同时,ufunc解决方案应该足够了。

我能想到的一个解决方案是将Python函数转换为
numpy.ufunc

并在
应用中使用此选项:

In [50]: dfrm_test
Out[50]:
     A
0  the
1  the
2  the
3  the
4  the
5  the
6  the
7  the
8  the
9  the

In [51]: dfrm_test["A"].apply(np.frompyfunc((lambda x: x[0:2]), 1, 1))
Out[51]:
0    th
1    th
2    th
3    th
4    th
5    th
6    th
7    th
8    th
9    th
Name: A

In [52]: pandas.version.version
Out[52]: '0.7.3'

In [53]: dfrm_test["A"].apply(lambda x: x[0:2])
Out[53]:
0    the
1    the
Name: A

尝试使用dfrm_test.A.map(lambda x:x[0:2])

从0.8.1开始使用:

In [47]: dfrm_test.A.str[:2]
Out[47]: 
0    th
1    th
2    th
3    th
4    th
5    th
6    th
7    th
8    th
9    th
Name: A

熊猫0.8返回进行
dfrm_测试[“A”]。应用(lambda x:x[0:2])
10次
th
。您确认这只是版本7.2-1中的一个错误吗??请注意,我在问题的底部提到,我无法摆脱使用这个版本。我不知道,我现在无法检查它。如果我在0.8上遇到同样的问题,我可以尝试找到解决方案,但如果没有7.2,我就无法解决。更正:我有0.7.3版。这是我早些时候报道的热情洋溢的分布。同样的bug仍在发生。这是可行的,但是我认为这也是一个解决办法,因为它没有解决“代码>应用< /COD>不符合承诺的事实。您是否可以验证
map
是否在
apply
将起作用的所有相同情况下都起作用?我也不喜欢从序列的
map
到数据帧的
applymap
之间的不一致性。我不确定这是否是
Series的“变通方法”。map
是元素操作的预期方法
Series.apply
将首先尝试将整个系列传递到输入函数中,并且只有在引发异常时才会返回元素操作。这与
apply
的文档及其0.8.1行为相矛盾,在该行为中,它成功地执行了上面示例的元素版本,而版本0.7.3似乎使用了您描述的逻辑。因为
apply
应该在0.7.3中工作,就像在0.8.1中一样(根据文档),所以我认为这是一种变通方法<代码>映射
很好,但应用应该可以。我在github master上,它不工作;它可能是偶然在0.8.1中工作的<代码>应用的设计目的是,您可以应用ufunc并获取索引完整的序列。看一下源代码,它尝试调用func(self)并将其包装在try/except块中,然后在except中调用map\u expert。在您的示例中,您提供的函数可以获取一个系列并返回一个系列,但不执行元素操作,因此代码无法知道如何触发元素大小写。为了明确说明您希望按元素应用输入函数,您必须使用
Series.map
。尽管我同意您的看法,但apply的docstring在这方面还不清楚。我们可以为应用改进文档。
In [47]: dfrm_test.A.str[:2]
Out[47]: 
0    th
1    th
2    th
3    th
4    th
5    th
6    th
7    th
8    th
9    th
Name: A