提问人:sweetdream 提问时间:5/29/2012 最后编辑:Communitysweetdream 更新时间:7/30/2019 访问量:2633
如何使用来自另一个 DataFrame 的输入以最佳方式将函数应用于 DataFrame 的所有项?
How to optimally apply a function on all items of a dataframe using inputs from another dataframe?
问:
我是 python 的新手,我正在努力用熊猫做简单的事情。我想将相同的函数应用于给定数据集的每个项目,但使用与时间相关的参数。
我正在使用以时间戳为索引的熊猫。DataFrame
比方说:
a(i,j) 是数据帧 A 中 j 列中的第 i 个元素(时间戳/索引 = i 和列 = j)
b(i) 是数据帧 B 中的第 i 个元素(具有单列)
我想计算:
c(i, j) = fct(a(i, j), b(i))
其中 fct 是一个有两个参数的函数 z = fct(x, y)
我写了一个代码,可以正确地做到这一点,但它可能不是最佳的(非常慢)。 对于示例,我只是使用了一个简单的函数 fct(但在 reallity 中它更复杂)
输入:
- df_data:带有 index=timestamp 和几列
pandas.DataFrame
- df_parameter:有 1 列包含瞬态参数
pandas.DataFrame
代码如下:
# p.concat is required as timestamps are not identical in df_data & df_parameters
import numpy as np
import pandas as p
temp = p.concat([df_data, df_parameter], join='inner', axis=1)
index = temp.index
np_data = temp[nacelleWindSpeeds.columns].values
np_parameter = temp[airDensity.columns].values
import math
def fct(x, y):
return math.pow(x, y)
def test(np_data, np_parameter):
np_result = np.empty(np_data.shape, dtype=float)
it = np.nditer(np_data, flags=['multi_index'])
while not it.finished:
np_result[it.multi_index] = fct(it[0].item(),
np_parameter[it.multi_index[0]][0])
it.iternext()
df_final=p.DataFrame(data=np_result, index=index)
return df_final
final=test(np_data, np_parameter)
final.to_csv(r'C:\temp\test.csv', sep=';')
以下是一些示例数据:
df_data
01/03/2010 00:00 ; 9 ; 5 ; 7
01/03/2010 00:10 ; 9 ; 1 ; 4
01/03/2010 00:20 ; 5 ; 3 ; 8
01/03/2010 00:30 ; 7 ; 7 ; 1
01/03/2010 00:40 ; 8 ; 2 ; 3
01/03/2010 00:50 ; 0 ; 3 ; 4
01/03/2010 01:00 ; 4 ; 3 ; 2
01/03/2010 01:10 ; 6 ; 2 ; 2
01/03/2010 01:20 ; 6 ; 8 ; 5
01/03/2010 01:30 ; 7 ; 7 ; 0
df_parameter
01/03/2010 00:00 ; 2
01/03/2010 00:10 ; 5
01/03/2010 00:20 ; 2
01/03/2010 00:30 ; 3
01/03/2010 00:40 ; 0
01/03/2010 00:50 ; 2
01/03/2010 01:00 ; 4
01/03/2010 01:10 ; 3
01/03/2010 01:20 ; 3
01/03/2010 01:30 ; 1
最后
01/03/2010 00:00 ; 81 ; 25 ; 49
01/03/2010 00:10 ; 59049 ; 1 ; 1024
01/03/2010 00:20 ; 25 ; 9 ; 64
01/03/2010 00:30 ; 343 ; 343 ; 1
01/03/2010 00:40 ; 1 ; 1 ; 1
01/03/2010 00:50 ; 0 ; 9 ; 16
01/03/2010 01:00 ; 256 ; 81 ; 16
01/03/2010 01:10 ; 216 ; 8 ; 8
01/03/2010 01:20 ; 216 ; 512 ; 125
01/03/2010 01:30 ; 7 ; 7 ; 0
非常感谢您的帮助,
帕特里克
答:
1赞
bmu
5/30/2012
#1
不知道这是否是最佳方法,但这更简单,应该更有效,因为它使用矢量化函数进行计算:
def func(x, y):
return x ** y
data = pd.read_csv('data.dat', sep=';', index_col=0, parse_dates=True,
header=None, names='abc')
para = pd.read_csv('parameter.dat', sep=';', index_col=0, parse_dates=True,
header=None, names=['para'])
for col in data:
data['%s_result' % col] = func(data[col], para.para)
print data
结果
a b c a_result b_result c_result
2010-01-03 00:00:00 9 5 7 81 25 49
2010-01-03 00:10:00 9 1 4 59049 1 1024
2010-01-03 00:20:00 5 3 8 25 9 64
2010-01-03 00:30:00 7 7 1 343 343 1
2010-01-03 00:40:00 8 2 3 1 1 1
2010-01-03 00:50:00 0 3 4 0 9 16
2010-01-03 01:00:00 4 3 2 256 81 16
2010-01-03 01:10:00 6 2 2 216 8 8
2010-01-03 01:20:00 6 8 5 216 512 125
2010-01-03 01:30:00 7 7 0 7 7 0
如果你的实际函数更复杂,你甚至应该尝试对它进行矢量化,或者使用 numpy.vectorize() 作为下一个最佳解决方案。
评论
0赞
sweetdream
5/30/2012
您好,感谢您的回复和这个漂亮的表述。不幸的是,只有当您能够使用矢量化函数时,这才正常工作。就我而言,我的函数使用字典,我认为这不能矢量化。我错了?
0赞
bmu
5/30/2012
@user1415325 在大多数情况下,您可以对函数进行矢量化,并且应该这样做以提高效率。你有没有看过下一个最佳解决方案?numpy.vectorize()
0赞
sweetdream
6/4/2012
多谢。这确实是我所缺少的。“神奇的”numpy.vectorize() 函数!!!再次感谢。
0赞
bmu
6/4/2012
@user1415325我更新了答案。如果这回答了您的问题,请考虑将答案标记为已解决。
0赞
sweetdream
6/5/2012
奇怪的是,首先从 DataFrame 中提取数据(作为 numpy 数组),然后运行函数,最后重建一个 DataFrame,速度更快......
0赞
nathanielng
9/5/2015
#2
一种方法是使用函数,或者 ;也可以使用 lambda 函数来做到这一点。例如:map
numpy.vectorize
import numpy as np
def fct(x, y):
return x**y
A = np.array([[9, 5, 7],
[9, 1, 4],
[5, 3, 8],
[7, 7, 1],
[8, 2, 3],
[0, 3, 4],
[4, 3, 2],
[6, 2, 2],
[6, 8, 5],
[7, 7, 0]])
B = np.array([2, 5, 2, 3, 0, 2, 4, 3, 3, 1])
C1 = np.asarray(map(fct, A, B))
C2 = np.asarray(map(lambda x,y: x**y, A, B))
vfunc = np.vectorize(fct)
C3 = vfunc(A, np.row_stack(B))
或通过 Pandas:
import pandas as pd
pdA = pd.DataFrame(A)
pdB = pd.DataFrame(B)
C4 = np.asarray(map(lambda x,y: x**y, pdA.values, pdB.values))
pdC = pd.DataFrame(C4)
请注意,C1、C2、C3 和 C4 都相等:
>>> print np.array_equal(C1,C2), np.array_equal(C2,C3), np.array_equal(C3,C4)
True True True
评论