熊猫:如何对单个列使用apply()函数?


254

我有两列的熊猫数据框。我需要在不影响第二列的情况下更改第一列的值,并只更改第一列的值即可获取整个数据帧。我该如何使用大熊猫应用程序?


4
请发布一些输入样本数据和所需的输出。
法比奥·拉曼纳

apply在这种情况下,几乎不要使用。而是直接在列上操作。
泰德·彼得鲁

正如Ted Petrou所说,请避免使用apply尽可能多的东西。如果不确定是否需要使用它,则可能不需要。我建议看看我什么时候应该在代码中使用pandas apply()?
cs95

问题还不是很清楚:是将函数应用于列的每个元素还是将函数整体应用于列(例如:反转列)?
皮埃尔·阿尔巴瑞德

Answers:


336

给定一个示例数据框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

9
apply切勿在这种情况下使用
Ted Petrou

5
@TedPetrou,您说得很对,这只是OP所要求的如何在单个列上应用通用函数的示例。
法比奥·拉曼纳

14
当我尝试执行此操作时,收到以下警告:“试图在DataFrame的切片副本上设置一个值。尝试改用.loc [row_indexer,col_indexer] = value”
dagrun

24
出于好奇:在这种情况下为什么不应该申请?到底是什么情况?
本叔叔

19
@UncleBenBen通常在行上apply使用内部循环,该循环比矢量化函数要慢得多,例如df.a = df.a / 2(请参阅Mike Muller答案)。
法比奥·拉曼纳

66

对于更好使用的单列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

78
为什么map()apply()单列更好?
ChaimG'2

2
这非常有用。我用它从存储在列中的路径中提取文件名df['file_name'] = df['Path'].map(lambda a: os.path.basename(a))
mmann1123 '18

46
map()用于Series(即单列),一次在一个单元格上操作,而apply()用于DataFrame,一次在整行上操作。
jpcgt

3
@jpcgt这是否意味着映射比在这种情况下适用要快?
维拉戈斯

@ChaimG我看到这个操作系统很好地解释了:stackoverflow.com/a/19798528/571828
象嘉道

40

您根本不需要功能。您可以直接处理整个列。

示例数据:

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

如果我想用“ /”分隔列中的每个元素并采用第一部分怎么办?
K47

12

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

可以使用assign:这可能assign对现有列有效,因为文档指出(重点是我的):

将新列分配给DataFrame。

返回一个新对象,该对象具有除新列之外的所有原始列。重新分配的现有列将被覆盖

简而言之:

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中选择正确的列。


9

如果您真的很关心apply函数的执行速度,并且有庞大的数据集需要处理,则可以使用swifter加快执行速度,以下是在swifter上实现pandas数据框的示例:

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内核都能计算结果,因此比正常的应用功能要快得多。尝试让我知道它是否对您有用。


1

让我尝试使用日期时间并考虑空值或空白的复杂计算。我正在减少30年的datetime列,并使用apply方法以及lambda转换datetime格式。Line if x != '' else 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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.