Python 如何对单个列使用apply()函数?

Python 如何对单个列使用apply()函数?,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个有两列的熊猫数据框。我需要在不影响第二列的情况下更改第一列的值,并在仅更改第一列值的情况下返回整个数据帧。如何使用apply in pandas实现这一点?给定一个示例数据帧df,如下所示: a,b 1,2 2,3 3,4 4,5 你想要的是: df['a'] = df['a'].apply(lambda x: x + 1) 这将返回: a b 0 2 2 1 3 3 2 4 4 3 5 5 对于单个列,最好使用map(),如下所示: df = pd.Dat

我有一个有两列的熊猫数据框。我需要在不影响第二列的情况下更改第一列的值,并在仅更改第一列值的情况下返回整个数据帧。如何使用apply in pandas实现这一点?

给定一个示例数据帧
df
,如下所示:

a,b
1,2
2,3
3,4
4,5
你想要的是:

df['a'] = df['a'].apply(lambda x: x + 1)
这将返回:

   a  b
0  2  2
1  3  3
2  4  4
3  5  5

对于单个列,最好使用
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

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

示例数据:

>>> 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

尽管给定的响应是正确的,但它们修改了初始数据帧,这并不总是可取的(并且,鉴于OP询问的示例“使用
apply
”,它们可能需要一个返回新数据帧的版本,正如
apply
所做的那样)

这可以使用:
分配给现有列是有效的,如文档所述(重点是我的):

将新列分配给数据帧

返回一个新对象,其中包含除新列之外的所有原始列重新分配的现有列将被覆盖

简言之:

[1]中的
:将熊猫作为pd导入
在[2]中,df=pd.DataFrame([{'a':15,'b':15,'c':5},{'a':20,'b':10,'c':7},{'a':25,'b':30,'c':9})
[3]中:df.assign(a=lambda-df:df.a/2)
出[3]:
a、b、c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9
In[4]:df
出[4]:
a、b、c
0  15  15  5
1  20  10  7
2  25  30  9

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

如果您真正关心apply函数的执行速度,并且需要处理大量数据集,则可以使用quifter来加快执行速度,以下是熊猫数据帧上的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核心计算结果,因此它将比正常的应用函数快得多。请尝试告诉我它是否对您有用。

让我尝试使用datetime并考虑空值或空格的复杂计算。我正在使用
apply
方法以及
lambda
和转换日期时间格式,将日期时间列缩短30年。行<代码>如果x!=''否则x将相应地处理所有空白或空

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)

给定以下数据帧
df
和函数
complex\u函数

将熊猫作为pd导入
def复数_函数(x,y=0):
如果x>5且x>y:
返回1
其他:
返回2
df=pd.DataFrame(数据={'col1':[1,4,6,2,7],'col2':[6,7,1,2,8]})
有几种解决方案可以仅在一列上使用apply()。下面我将详细解释它们

一、简单解决办法 直截了当的解决方案来自@Fabio Lamanna:

df['col1']=df['col1'].应用(复数函数)
输出:

     col1  col2
  0     2     6
  1     2     7
  2     1     1
  3     2     2
  4     1     8
     col1  col2
  0     2     6
  1     2     7
  2     1     1
  3     2     2
  4     2     8
仅修改第一列,第二列不变。这个解决方案很漂亮。它只是一行代码,读起来几乎像英语:“取'col1'并将函数complex_函数应用于它。”

但是,如果您需要来自另一列的数据,例如“col2”,它将不起作用。如果要将'col2'的值传递给
复杂函数
的变量
y
,则需要其他内容

二,。使用整个数据帧的解决方案 或者,您可以使用所述的整个数据帧,或者:

df['col1']=df.apply(λx:complex_函数(x['col1']),轴=1)
或者,如果您喜欢(像我一样)没有lambda函数的解决方案:

def apply_complex_函数(x):返回complex_函数(x['col1'])
df['col1']=df.apply(应用复杂函数,轴=1)
这个解决方案中有很多问题需要解释。函数的作用是:pd.Series和pd.DataFrame。但是不能使用
df['col1']=df.apply(complex_function).loc[:,'col1']
,因为它会抛出
ValueError

因此,您需要给出要使用哪个列的信息。要使事情复杂化,请使用apply()函数。要解决这个问题,您需要定义一个(lambda)函数,其中列
x['col1']
作为参数;i、 我们将列信息包装在另一个函数中

不幸的是,axis参数的默认值为零(
axis=0
),这意味着它将尝试按列而不是按行执行。这在第一个解决方案中不是问题,因为我们给apply()一个pd.Series。但是现在输入是一个数据帧,我们必须是显式的(
axis=1
)。(我很惊讶我经常忘记这一点。)

您是否喜欢带有lambda函数的版本是主观的。在我看来,这行代码非常复杂,即使没有lambda函数也可以读取。您只需要(lambda)函数作为包装器。这只是锅炉代码。读者不应该为此烦恼

现在,您可以轻松修改此解决方案,以考虑第二列:

def apply_complex_函数(x):返回complex_函数(x['col1'],x['col2'])
df['col1']=df.apply(应用复杂函数,轴=1)
输出:

     col1  col2
  0     2     6
  1     2     7
  2     1     1
  3     2     2
  4     1     8
     col1  col2
  0     2     6
  1     2     7
  2     1     1
  3     2     2
  4     2     8
在索引4处,该值已从1更改为2,因为第一个条件
7>5
为真,而第二个条件
7>8
为假

请注意,您只需要更改代码的第一行(即函数),而不需要更改第二行


旁注 切勿将列信息放入函数中

def坏主意(x):
返回x['col1']**2
通过这样做,您可以使一个通用函数依赖于一个列名!这是一个坏主意,因为下次要使用此函数时,y