2

我有一列包含字符串的数据,我想创建一个新列,该列仅采用相应数据字符串中的前两个字符。

为此使用该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 恰好广播了它,那么它将起作用。如果没有,那么它不会。

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

对 Series 的值调用函数。可以是 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 包装器。

我的猜测是,在代码中,有人试图使用numpy.vectorizenumpy.frompyfunc在 try-except 语句中。也许它与我正在使用的特定 lambda 函数无法正常工作,因此在except部分代码中,它默认仅依赖于通用 NumPy 广播。

如果可能的话,最好从 Pandas 开发人员那里得到一些确认。但与此同时,ufunc 解决方法就足够了。

4

3 回答 3

3

我能想到的一种解决方法是将 Python 函数转换为numpy.ufuncwith numpy.frompyfunc

numpy.frompyfunc((lambda x: x[0:2]), 1, 1)

并将其用于apply

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
于 2012-09-12T18:09:32.177 回答
1

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

于 2012-09-12T22:25:19.500 回答
1

这适用于 pandas 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
于 2012-10-24T16:19:17.057 回答