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

我在单个文本列上有一个函数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()。因此,很多问题和答案都不太相关。


当前回答

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

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.apply(extract_text_features,axis = 1)

函数在哪里返回行

def extract_text_features(row):
      row['new_col1'] = value1
      row['new_col2'] = value2
      return row

基于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/ !

总结:如果您只想创建几个列,请使用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)

这是我过去所做的

df = pd.DataFrame({'textcol' : np.random.rand(5)})

df
    textcol
0  0.626524
1  0.119967
2  0.803650
3  0.100880
4  0.017859

df.textcol.apply(lambda s: pd.Series({'feature1':s+1, 'feature2':s-1}))
   feature1  feature2
0  1.626524 -0.373476
1  1.119967 -0.880033
2  1.803650 -0.196350
3  1.100880 -0.899120
4  1.017859 -0.982141

为完整性而编辑

pd.concat([df, df.textcol.apply(lambda s: pd.Series({'feature1':s+1, 'feature2':s-1}))], axis=1)
    textcol feature1  feature2
0  0.626524 1.626524 -0.373476
1  0.119967 1.119967 -0.880033
2  0.803650 1.803650 -0.196350
3  0.100880 1.100880 -0.899120
4  0.017859 1.017859 -0.982141

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

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)