这是一个自我回答的QnA,旨在指导用户应用的缺陷和好处.
我已经看到很多关于Stack Overflow问题的答案涉及使用apply.我也看到用户评论他们说" apply很慢",应该避免".
我已经阅读了很多关于性能主题的文章,解释apply很慢.我还在文档中看到了一个关于如何apply简单地传递UDF的便利函数的免责声明(现在似乎无法找到).因此,普遍的共识是,apply如果可能,应该避免.但是,这引发了以下问题:
apply是如此糟糕,那为什么它在API中呢?apply- 免费?apply是不错的(比其他可能的解决方案更好)?我正在使用Pandas数据帧,并希望创建一个新列作为现有列的函数.我还没有看到之间的速度差的一个很好的讨论df.apply()和np.vectorize(),所以我想我会问这里.
熊猫apply()功能很慢.根据我的测量结果(如下面的一些实验所示),使用np.vectorize()比使用DataFrame功能快25倍(或更多)apply(),至少在我的2016 MacBook Pro上使用.这是预期的结果,为什么?
例如,假设我有以下带N行的数据框:
N = 10
A_list = np.random.randint(1, 100, N)
B_list = np.random.randint(1, 100, N)
df = pd.DataFrame({'A': A_list, 'B': B_list})
df.head()
# A B
# 0 78 50
# 1 23 91
# 2 55 62
# 3 82 64
# 4 99 80
Run Code Online (Sandbox Code Playgroud)
进一步假设我想创建一个新列作为两列的函数A和B.在下面的例子中,我将使用一个简单的函数divide().要应用该功能,我可以使用df.apply()或np.vectorize():
def divide(a, b):
if b == 0:
return …Run Code Online (Sandbox Code Playgroud) 使用DataFrame的子集进行iterrows的最佳方法是什么?
我们来看以下简单示例:
import pandas as pd
df = pd.DataFrame({
'Product': list('AAAABBAA'),
'Quantity': [5,2,5,10,1,5,2,3],
'Start' : [
DT.datetime(2013,1,1,9,0),
DT.datetime(2013,1,1,8,5),
DT.datetime(2013,2,5,14,0),
DT.datetime(2013,2,5,16,0),
DT.datetime(2013,2,8,20,0),
DT.datetime(2013,2,8,16,50),
DT.datetime(2013,2,8,7,0),
DT.datetime(2013,7,4,8,0)]})
df = df.set_index(['Start'])
Run Code Online (Sandbox Code Playgroud)
现在我想使用itterrows函数修改此DataFrame的子集,例如:
for i, row_i in df[df.Product == 'A'].iterrows():
row_i['Product'] = 'A1' # actually a more complex calculation
Run Code Online (Sandbox Code Playgroud)
但是,这些变化并不存在.
是否有可能(使用索引'i'进行手动查找除外)对原始Dataframe进行持久更改?
我有几个'过去'和'现在'变量,我想执行一个简单的百分比变化' 行 '.例如:((exports_now - exports_past)/exports_past)).
这两个问题实现了这一点,但是当我尝试类似的方法时,我得到一个错误,我的函数增量获得了一个未知参数axis.
exports_ past exports_ now imports_ past imports_ now ect.(6 other pairs)
.23 .45 .43 .22 1.23
.13 .21 .47 .32 .23
0 0 .41 .42 .93
.23 .66 .43 .22 .21
0 .12 .47 .21 1.23
Run Code Online (Sandbox Code Playgroud)
在第一个问题的答案之后,
def deltas(row):
'''
simple pct change
'''
if int(row[0]) == 0 and int(row[1]) == 0:
return 0
elif int(row[0]) == 0:
return np.nan
else:
return ((row[1] - row[0])/row[0]) …Run Code Online (Sandbox Code Playgroud) 我正在尝试连接 Pandas DataFrame 中的两列。问题是当任一系列中都存在 None 值时,结果为 NaN。由于真实数据非常大,有保留原始None值供以后参考的价值,希望不要更改列中的原始值。有没有办法在熊猫中实现这一目标?
创建一个示例数据帧:
import pandas as pd
f = pd.DataFrame([['a', 'b','c','a', 'b','c'],['1', '2','3', '4', '5','6', ]])
f = f.transpose()
f.columns = ['xx', 'yy']
f.xx[0] = None
f.yy[0] = None
f.xx[2] = None
f.yy[3] = None
xx yy
0 None None
1 b 2
2 None 3
3 a None
4 b 5
5 c 6
Run Code Online (Sandbox Code Playgroud)
我试过f['new_str'] = f.xx + f.yy和f['new_str'] = f['xx'] + f['yy']。如果任何值是 None 类型,则两者都将连接值设置为 NaN。我认为这是由于熊猫如何处理None类型。None 类型和 str …
假设这是我的功能:
def function(x):
return x.str.lower()
Run Code Online (Sandbox Code Playgroud)
这是我的 DataFrame (df)
A B C D
0 1.67430 BAR 0.34380 FOO
1 2.16323 FOO -2.04643 BAR
2 0.19911 BAR -0.45805 FOO
3 0.91864 BAR -0.00718 BAR
4 1.33683 FOO 0.53429 FOO
5 0.97684 BAR -0.77363 BAR
Run Code Online (Sandbox Code Playgroud)
我想将该函数仅应用于列B和D. (将它应用于完整的 DataFrame 不是答案,因为它会在数字列中产生 NaN 值)。
这是我的基本想法: df.apply(function, axis=1)
但我无法理解如何选择不同的列来应用该函数。我已经尝试过按数字位置、名称等进行索引的所有方式。
我花了很多时间来阅读这个。这不是以下任何一项的直接副本:
我想逐行为两个数据帧列df1和df2建模这个excel公式:
=IF(df1 > df2; df2; df2 - df1)
Run Code Online (Sandbox Code Playgroud)
我知道这可以用Python中的map来完成,但不知道怎么做.我可以使用for循环和if-else语句来完成它,但它使我的代码更难阅读.
你能帮助我吗?
我有一个带有列Longitude和的pandas数据框Latitude.我想X和Y他们相处.utm调用from_latlon中有一个函数可以执行此操作.它接收Latitude和Longitude并给出[X,Y].这是我做的:
def get_X(row):
return utm.from_latlon(row['Latitude'], row['Longitude'])[0]
def get_Y(row):
return utm.from_latlon(row['Latitude'], row['Longitude'])[1]
df['X'] = df.apply(get_X, axis=1)
df['Y'] = df.apply(get_Y, axis=1)
Run Code Online (Sandbox Code Playgroud)
我想定义一个函数get_XY并from_latlon只应用一次来节省时间.我看了一下这里,这里和这里,但我找不到用一个apply函数制作两列的方法.谢谢.
pandas ×8
python ×7
apply ×2
performance ×2
arrays ×1
dataframe ×1
loops ×1
map-function ×1
numpy ×1
python-3.x ×1
subset ×1