你能告诉我什么时候使用这些矢量化方法和基本的例子吗?

我看到map是一个系列方法,而其余的是DataFrame方法。我对apply和applymap方法感到困惑。为什么我们有两个方法来应用一个函数到一个数据帧?再一次,简单的例子说明用法将是伟大的!


当前回答

apply工作在数据帧的行/列基础上 applymap在DataFrame上按元素工作 map在Series上按元素工作


直接摘自Wes McKinney的Python for Data Analysis一书,第132页(我强烈推荐这本书):

另一个常见操作是将一维数组上的函数应用到每一列或行。DataFrame的apply方法是这样做的:

In [116]: frame = DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [117]: frame
Out[117]: 
               b         d         e
Utah   -0.029638  1.081563  1.280300
Ohio    0.647747  0.831136 -1.549481
Texas   0.513416 -0.884417  0.195343
Oregon -0.485454 -0.477388 -0.309548

In [118]: f = lambda x: x.max() - x.min()

In [119]: frame.apply(f)
Out[119]: 
b    1.133201
d    1.965980
e    2.829781
dtype: float64

许多最常见的数组统计(如sum和mean)是DataFrame方法, 所以没有必要使用apply。

也可以使用元素级Python函数。假设您希望从帧中的每个浮点值计算一个格式化字符串。你可以用applymap:

In [120]: format = lambda x: '%.2f' % x

In [121]: frame.applymap(format)
Out[121]: 
            b      d      e
Utah    -0.03   1.08   1.28
Ohio     0.65   0.83  -1.55
Texas    0.51  -0.88   0.20
Oregon  -0.49  -0.48  -0.31

命名为applymap的原因是Series有一个map方法用于应用一个按元素划分的函数:

In [122]: frame['e'].map(format)
Out[122]: 
Utah       1.28
Ohio      -1.55
Texas      0.20
Oregon    -0.31
Name: e, dtype: object

其他回答

除了其他答案,在一个系列中还有map和apply。

Apply可以从一个系列中生成一个DataFrame;然而,map只会在另一个系列的每个单元格中放入一个系列,这可能不是您想要的。

In [40]: p=pd.Series([1,2,3])
In [41]: p
Out[31]:
0    1
1    2
2    3
dtype: int64

In [42]: p.apply(lambda x: pd.Series([x, x]))
Out[42]: 
   0  1
0  1  1
1  2  2
2  3  3

In [43]: p.map(lambda x: pd.Series([x, x]))
Out[43]: 
0    0    1
1    1
dtype: int64
1    0    2
1    2
dtype: int64
2    0    3
1    3
dtype: int64
dtype: object

另外,如果我有一个带有副作用的函数,比如“连接到web服务器”,为了清晰起见,我可能会使用apply。

series.apply(download_file_for_every_element) 

Map不仅可以使用函数,还可以使用字典或其他系列。假设你想操纵排列。

Take

1 2 3 4 5
2 1 4 5 3

这个排列的平方是

1 2 3 4 5
1 2 5 3 4

你可以用map来计算。不确定self-application是否有文档记录,但它在0.15.1中可以工作。

In [39]: p=pd.Series([1,0,3,4,2])

In [40]: p.map(p)
Out[40]: 
0    0
1    1
2    4
3    2
4    3
dtype: int64

我只是想指出一点,我在这方面有过一些挣扎

def f(x):
    if x < 0:
        x = 0
    elif x > 100000:
        x = 100000
    return x

df.applymap(f)
df.describe()

这不会修改数据帧本身,必须重新分配:

df = df.applymap(f)
df.describe()

快速的总结

DataFrame。Apply一次操作整个行或列。 DataFrame。applymap系列。apply和Series。Map操作1 元素。

系列。应用和系列。地图是相似的,经常可以互换。下面osa的回答中讨论了他们之间的一些细微差异。

原因:

下面的示例显示apply和applymap应用到一个DataFrame。

map函数只能应用在Series上。不能在DataFrame上应用map。

需要记住的是,apply可以做任何applymap可以做的事情,但apply有额外的选项。

X因子选项是:axis和result_type,其中result_type仅在axis=1时有效(对于列)。

df = DataFrame(1, columns=list('abc'),
                  index=list('1234'))
print(df)

f = lambda x: np.log(x)
print(df.applymap(f)) # apply to the whole dataframe
print(np.log(df)) # applied to the whole dataframe
print(df.applymap(np.sum)) # reducing can be applied for rows only

# apply can take different options (vs. applymap cannot)
print(df.apply(f)) # same as applymap
print(df.apply(sum, axis=1))  # reducing example
print(df.apply(np.log, axis=1)) # cannot reduce
print(df.apply(lambda x: [1, 2, 3], axis=1, result_type='expand')) # expand result

作为旁注,不应将Series映射函数与Python映射函数混淆。

第一个应用在Series上,用于映射值,第二个应用到可迭代对象的每个项。


最后,不要混淆dataframe apply方法和groupby apply方法。

基于cs95的答案

map在Series ONLY上定义 applymap只在DataFrames上定义 apply定义在BOTH上

举几个例子

In [3]: frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [4]: frame
Out[4]:
            b         d         e
Utah    0.129885 -0.475957 -0.207679
Ohio   -2.978331 -1.015918  0.784675
Texas  -0.256689 -0.226366  2.262588
Oregon  2.605526  1.139105 -0.927518

In [5]: myformat=lambda x: f'{x:.2f}'

In [6]: frame.d.map(myformat)
Out[6]:
Utah      -0.48
Ohio      -1.02
Texas     -0.23
Oregon     1.14
Name: d, dtype: object

In [7]: frame.d.apply(myformat)
Out[7]:
Utah      -0.48
Ohio      -1.02
Texas     -0.23
Oregon     1.14
Name: d, dtype: object

In [8]: frame.applymap(myformat)
Out[8]:
            b      d      e
Utah     0.13  -0.48  -0.21
Ohio    -2.98  -1.02   0.78
Texas   -0.26  -0.23   2.26
Oregon   2.61   1.14  -0.93

In [9]: frame.apply(lambda x: x.apply(myformat))
Out[9]:
            b      d      e
Utah     0.13  -0.48  -0.21
Ohio    -2.98  -1.02   0.78
Texas   -0.26  -0.23   2.26
Oregon   2.61   1.14  -0.93


In [10]: myfunc=lambda x: x**2

In [11]: frame.applymap(myfunc)
Out[11]:
            b         d         e
Utah    0.016870  0.226535  0.043131
Ohio    8.870453  1.032089  0.615714
Texas   0.065889  0.051242  5.119305
Oregon  6.788766  1.297560  0.860289

In [12]: frame.apply(myfunc)
Out[12]:
            b         d         e
Utah    0.016870  0.226535  0.043131
Ohio    8.870453  1.032089  0.615714
Texas   0.065889  0.051242  5.119305
Oregon  6.788766  1.297560  0.860289