我有一个有两列的熊猫数据框架。我需要在不影响第二列的情况下改变第一列的值,并返回整个数据框架,只是第一列的值改变了。我如何在熊猫中使用apply()来做到这一点?


当前回答

你根本不需要函数。您可以直接处理整个列。

示例数据:

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

a列中所有值的一半:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

其他回答

如果你真的很关心你的apply函数的执行速度,并且你有一个巨大的数据集要处理,你可以使用swifter来使执行速度更快,这里有一个在pandas数据框架上的swifter的例子:

import pandas as pd
import swifter

def fnc(m):
    return m*3+4

df = pd.DataFrame({"m": [1,2,3,4,5,6], "c": [1,1,1,1,1,1], "x":[5,3,6,2,6,1]})

# apply a self created function to a single column in pandas
df["y"] = df.m.swifter.apply(fnc)

这将使您的所有CPU核心计算结果,因此它将比普通应用函数快得多。试着让我知道它是否对你有用。

尽管给出的响应是正确的,但它们修改了初始数据帧,这并不总是可取的(并且,给定OP要求“使用apply”示例,可能它们想要一个返回新数据帧的版本,就像apply那样)。

这可以通过使用assign实现:如文档所述(重点是我的),对现有列进行赋值是有效的:

为数据框架分配新列。 返回一个包含所有原始列和新列的新对象。重新分配的现有列将被覆盖。

简而言之:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

In [3]: df.assign(a=lambda df: df.a / 2)
Out[3]: 
      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

In [4]: df
Out[4]: 
    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9

注意,函数将传递整个数据帧,而不仅仅是要修改的列,因此需要确保在lambda中选择了正确的列。

你根本不需要函数。您可以直接处理整个列。

示例数据:

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

a列中所有值的一半:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

对于单列最好使用map(),如下所示:

df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9



df['a'] = df['a'].map(lambda a: a / 2.)

      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

让我使用datetime并考虑null或空格来尝试一个复杂的计算。我在一个datetime列上减少30年,并使用apply方法以及lambda和转换datetime格式。行if x != "否则x将相应地处理所有空格或null。

df['Date'] = df['Date'].fillna('')
df['Date'] = df['Date'].apply(lambda x : ((datetime.datetime.strptime(str(x), '%m/%d/%Y') - datetime.timedelta(days=30*365)).strftime('%Y%m%d')) if x != '' else x)