您能否通过基本示例告诉我何时使用这些矢量化方法?
我看到这map
是一种Series
方法,而其余都是DataFrame
方法。我糊涂了约apply
和applymap
,虽然方法。为什么我们有两种将函数应用于DataFrame的方法?同样,简单的例子可以很好地说明用法!
您能否通过基本示例告诉我何时使用这些矢量化方法?
我看到这map
是一种Series
方法,而其余都是DataFrame
方法。我糊涂了约apply
和applymap
,虽然方法。为什么我们有两种将函数应用于DataFrame的方法?同样,简单的例子可以很好地说明用法!
Answers:
直接来自Wes McKinney的《Python for Data Analysis》一书,第16页。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
总结起来,apply
在DataFrame的行/列基础上工作,在DataFrame applymap
上按map
元素工作,在Series上按元素工作。
func
为lambda x: [func(y) for y in x]
,并
map
和applymap
两个工作要素的角度来看,我希望单一的方法(map
或applymap
)其将工作既为一个系列和一个数据帧。可能还有其他设计注意事项,Wes McKinney决定提出两种不同的方法。
applymap
与groupby
熊猫的功能一起做?
map
,applymap
和:上下文问题ap
ply
第一个主要区别:定义
map
仅在系列上定义applymap
仅在DataFrames上定义apply
两者都定义第二个主要区别:输入参数
map
接受dict
S, Series
,或可调用applymap
并且apply
只接受可调用第三大区别:行为
map
对于系列是元素applymap
对于DataFrames是元素apply
也可以逐元素工作,但适用于更复杂的操作和聚合。行为和返回值取决于函数。四主要的区别(最重要的):用例
map
是用于将值从一个域映射到另一个域,因此针对性能进行了优化(例如df['A'].map({1:'a', 2:'b', 3:'c'})
)applymap
适用于跨多个行/列的元素转换(例如df[['A', 'B', 'C']].applymap(str.strip)
)apply
用于应用无法向量化的任何功能(例如df['sentences'].apply(nltk.sent_tokenize)
)脚注
map
通过字典/系列时,将基于该字典/系列中的键映射元素。缺少的值将在输出中记录为NaN。
applymap
在最新版本中,已针对某些操作进行了优化。您会发现applymap
比apply
某些情况下要快一些。我的建议是对它们都进行测试,并使用更好的方法。
map
针对元素映射和转换进行了优化。涉及字典或系列的操作将使熊猫能够使用更快的代码路径来获得更好的性能。Series.apply
返回用于汇总操作的标量,否则返回Series。同样适用于DataFrame.apply
。需要注意的是apply
,当某些NumPy的功能,如所谓的也有FastPaths的mean
,sum
等等。
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
不仅可以使用功能,还可以使用字典或其他系列。假设您要操纵排列。
采取
1 2 3 4 5
2 1 4 5 3
此排列的平方是
1 2 3 4 5
1 2 5 3 4
您可以使用进行计算map
。不知道自助申请是否已记录在案,但可以在中使用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
@jeremiahbuddha提到了apply在行/列上的工作,而applymap在元素上工作。但似乎您仍可以使用apply进行元素计算。
frame.apply(np.sqrt)
Out[102]:
b d e
Utah NaN 1.435159 NaN
Ohio 1.098164 0.510594 0.729748
Texas NaN 0.456436 0.697337
Oregon 0.359079 NaN NaN
frame.applymap(np.sqrt)
Out[103]:
b d e
Utah NaN 1.435159 NaN
Ohio 1.098164 0.510594 0.729748
Texas NaN 0.456436 0.697337
Oregon 0.359079 NaN NaN
只是想指出一点,因为我为此苦了一点
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()
df = modified_df
或设置inplace=True
标志来修改熊猫数据框。另外据帧,如果你传递一个数据帧到一个函数引用和函数修改数据帧将改变
.ix
还是.where
等不知道完整的解释是什么,当你需要重新分配,何时不。
我的理解:
从功能上看:
如果函数具有需要在列/行中进行比较的变量,请使用
apply
。
例如:lambda x: x.max()-x.mean()
。
如果要将函数应用于每个元素:
1>如果找到列/行,请使用 apply
2>如果适用于整个数据框,请使用 applymap
majority = lambda x : x > 17
df2['legal_drinker'] = df2['age'].apply(majority)
def times10(x):
if type(x) is int:
x *= 10
return x
df2.applymap(times10)
基于cs95的答案
map
仅在系列上定义applymap
仅在DataFrames上定义apply
两者都定义举一些例子
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
FOMO:
以下示例显示apply
并applymap
应用于DataFrame
。
map
函数仅适用于Series。您不能map
在DataFrame上申请。
需要记住的是, 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
map
附带说明一下,Series 函数不应与Python map
函数混淆。
第一个应用于Series,以映射值,第二个应用于迭代对象的每个项目。