逐行迭代2个Pandas Dataframe ,并将这些向量作为参数传递给函数

gmol1639  于 2022-09-21  发布在  其他
关注(0)|答案(3)|浏览(175)

我想对两个形状相同的 Dataframe 逐行迭代,将每个 Dataframe 中的行作为向量传递给函数,而不使用循环。本质上类似于R‘s mApply的东西。

我已经调查了一些,我所见过的最好的方法是在列表理解中使用MAP,但我做得不正确。然而,即使我们让它发挥作用,它似乎也有点笨拙--有没有更优雅的方法来做到这一点?这似乎应该是Pandas的一项功能。

import numpy as np
import pandas as pd
from scipy import stats

df1 = pd.DataFrame(np.random.randn(3,3))
df2 = pd.DataFrame(np.random.randn(3,3))

sd_array = np.array([0.02, 0.015, 0.2])

def helper_func(x, y):
   return stats.norm.pdf(x, loc=y, scale=sd_array).prod()

res_lst = []
row_cnt = df1.shape[0]

res = [list(map(helper_func, df1.iloc[i,:], df2.iloc[i,:])) for i in range(row_cnt)]
res_lst.append(res)

我目前编写它的方式没有给出错误,但也没有返回我想要的东西。我应该在输出中只有3个值,每个值对应于 Dataframe 的每行。

kqlmhetl

kqlmhetl1#

你可以只做helper_func(df1, df2),在helper_func中:return stats.norm.pdf(x, loc=y, scale=sd_array).prod(axis=1)。请注意,您的标度是这样的,返回的值几乎总是0。在PDF中使用Scale=100*SD_ARRAY至少会显示一些非零值。

事实上,在本例中您不需要 Dataframe :

import numpy as np
from scipy import stats

np.random.seed(1)

data1 = np.random.randn(3,3)
data2 = np.random.randn(3,3)

sd_array = np.array([0.02, 0.015, 0.2])

C = 100  # for demonstration purposes
def helper_func(x, y):
    return stats.norm.pdf(x, loc=y, scale=C*sd_array).prod(axis=1)

res = helper_func(data1, data2)
print(res)

收益率

array([0.0002616 , 0.00068695, 0.00035566])

但当使用 Dataframe 而不是data1data2时,NumPy/Pandas/Scipy足够灵活,可以识别二维值数组并使用它。

bis0qfac

bis0qfac2#

实现的问题在于,您需要迭代各行,并使用map对每行中的每个元素应用helper_func。因此,对helper_func的第一个调用是helpoer_func(df1.iloc[i, 0], df2.iloc[i, 0]),而不是在第一行。

您可以通过删除内部循环来修复实现:

res = [helper_func(df1.iloc[i,:], df2.iloc[i,:]) for i in range(row_cnt)]
smdncfj3

smdncfj33#

我更喜欢我另一个答案中的方法,使用NumPy向量计算,使用.prod(axis=1),但要回答标题中的问题:您可以使用zip.iterrows()

assert len(df1) == len(df2)  # just to check
res = [helper_func(row1, row2) for (_, row1), (_, row2) in 
       zip(df1.iterrows(), df2.iterrows())]

(这需要原始的helper_func,在.prod()方法中没有axis=1。)

您需要使用下划线来忽略.iterrows()附带的索引(在标准的Python中,它的功能相当于enumerate())。

相关问题