如何在熊猫身上做到这一点:

我在单个文本列上有一个函数extract_text_features,返回多个输出列。具体来说,该函数返回6个值。

该函数可以工作,但是似乎没有任何合适的返回类型(pandas DataFrame/ numpy数组/ Python列表),以便输出可以正确分配df。Ix [:,10:16] = df.textcol.map(extract_text_features)

所以我认为我需要回落到迭代与df.iterrows(),按此?

更新: 使用df.iterrows()迭代至少要慢20倍,因此我放弃并将该函数分解为6个不同的.map(lambda…)调用。

更新2:这个问题是在v0.11.0版本被问到的,在可用性df之前。在v0.16中改进了Apply或添加了df.assign()。因此,很多问题和答案都不太相关。


当前回答

对我来说,这很有效:

输入df

df = pd.DataFrame({'col x': [1,2,3]})
   col x
0      1
1      2
2      3

函数

def f(x):
    return pd.Series([x*x, x*x*x])

创建2个新列:

df[['square x', 'cube x']] = df['col x'].apply(f)

输出:

   col x  square x  cube x
0      1         1       1
1      2         4       8
2      3         9      27

其他回答

基于user1827356的答案,你可以使用df.merge一次性完成赋值:

df.merge(df.textcol.apply(lambda s: pd.Series({'feature1':s+1, 'feature2':s-1})), 
    left_index=True, right_index=True)

    textcol  feature1  feature2
0  0.772692  1.772692 -0.227308
1  0.857210  1.857210 -0.142790
2  0.065639  1.065639 -0.934361
3  0.819160  1.819160 -0.180840
4  0.088212  1.088212 -0.911788

编辑: 请注意内存消耗大,速度慢:https://ys-l.github.io/posts/2015/08/28/how-not-to-use-pandas-apply/ !

对于95%的用例来说,这是正确且最简单的方法:

>>> df = pd.DataFrame(zip(*[range(10)]), columns=['num'])
>>> df
    num
0    0
1    1
2    2
3    3
4    4
5    5

>>> def example(x):
...     x['p1'] = x['num']**2
...     x['p2'] = x['num']**3
...     x['p3'] = x['num']**4
...     return x

>>> df = df.apply(example, axis=1)
>>> df
    num  p1  p2  p3
0    0   0   0    0
1    1   1   1    1
2    2   4   8   16
3    3   9  27   81
4    4  16  64  256

在另外两个类似的问题上也有相同的答案。我更喜欢这样做的方式是将函数的返回值打包成一个系列:

def f(x):
    return pd.Series([x**2, x**3])

然后使用apply创建单独的列,如下所示:

df[['x**2','x**3']] = df.apply(lambda row: f(row['x']), axis=1)

对我来说,这很有效:

输入df

df = pd.DataFrame({'col x': [1,2,3]})
   col x
0      1
1      2
2      3

函数

def f(x):
    return pd.Series([x*x, x*x*x])

创建2个新列:

df[['square x', 'cube x']] = df['col x'].apply(f)

输出:

   col x  square x  cube x
0      1         1       1
1      2         4       8
2      3         9      27

总结:如果您只想创建几个列,请使用df[['new_col1','new_col2']] = df[['data1','data2']]。Apply (function_of_your_selection (x), axis=1)

对于这个解决方案,创建的新列数必须等于用作.apply()函数输入的列数。如果你想做别的事情,看看其他答案。

细节 假设你有两列数据框架。第一列是一个人10岁时的身高;第二个是20岁时的身高。

假设你需要计算每个人身高的平均值和每个人身高的和。每一行有两个值。

你可以通过下面即将应用的函数来实现:

def mean_and_sum(x):
    """
    Calculates the mean and sum of two heights.
    Parameters:
    :x -- the values in the row this function is applied to. Could also work on a list or a tuple.
    """

    sum=x[0]+x[1]
    mean=sum/2
    return [mean,sum]

你可以这样使用这个函数:

 df[['height_at_age_10','height_at_age_20']].apply(mean_and_sum(x),axis=1)

(需要明确的是:这个apply函数接受子集数据帧中每一行的值,并返回一个列表。)

然而,如果你这样做:

df['Mean_&_Sum'] = df[['height_at_age_10','height_at_age_20']].apply(mean_and_sum(x),axis=1)

您将创建一个包含[mean,sum]列表的新列,这可能是您希望避免的,因为这将需要另一个Lambda/Apply。

相反,您希望将每个值分解到它自己的列中。要做到这一点,你可以一次创建两个列:

df[['Mean','Sum']] = df[['height_at_age_10','height_at_age_20']]
.apply(mean_and_sum(x),axis=1)