假设我有一个DataFrame,要在其上计算两列之间的滚动或扩展Pearson相关性
import numpy as np
import pandas as pd
import scipy.stats as st
df = pd.DataFrame({'x': np.random.rand(10000), 'y': np.random.rand(10000)})
Run Code Online (Sandbox Code Playgroud)
利用内置pandas功能,可以快速计算出
expanding_corr = df['x'].expanding(50).corr(df['y'])
rolling_corr = df['x'].rolling(50).corr(df['y'])
Run Code Online (Sandbox Code Playgroud)
但是,如果我希望获得与这些相关性关联的p值,我能做的最好的事情就是定义一个自定义滚动函数并将其传递apply给groupby对象
def custom_roll(df, w, **kwargs):
v = df.values
d0, d1 = v.shape
s0, s1 = v.strides
a = np.lib.stride_tricks.as_strided(v, (d0 - (w - 1), w, d1), (s0, s0, s1))
rolled_df = pd.concat({
row: pd.DataFrame(values, columns=df.columns)
for row, values in zip(df.index[(w-1):], a)
})
return rolled_df.groupby(level=0, **kwargs)
c_df = custom_roll(df, …Run Code Online (Sandbox Code Playgroud) 假设我有两个时间戳记,分别是5小时范围内的开始/结束时间对。它们不一定是顺序的,也不能量化为小时。
import pandas as pd
start = pd.Series(pd.date_range('20190412',freq='H',periods=25))
# Drop a few indexes to make the series not sequential
start.drop([4,5,10,14]).reset_index(drop=True,inplace=True)
# Add some random minutes to the start as it's not necessarily quantized
start = start + pd.to_timedelta(np.random.randint(59,size=len(start)),unit='T')
end = start + pd.Timedelta('5H')
Run Code Online (Sandbox Code Playgroud)
现在假设我们有一些以分钟为单位的时间戳数据,其范围涵盖了所有开始/结束对。
data_series = pd.Series(data=np.random.randint(20, size=(75*60)),
index=pd.date_range('20190411',freq='T',periods=(75*60)))
Run Code Online (Sandbox Code Playgroud)
我们希望从和时间data_series范围内获得的值。可以在循环中天真地完成此操作startend
frm = []
for s,e in zip(start,end):
frm.append(data_series.loc[s:e].values)
Run Code Online (Sandbox Code Playgroud)
如我们所见,这种幼稚的方法遍历每对start和end日期,并从数据中获取值。
但是,如果实现len(start)较大,则此实现速度很慢。有没有办法利用pandas矢量功能执行这种逻辑?
我觉得这几乎就像我想应用.loc矢量,pd.Series而不是单个应用pd.Timestamp?
编辑 …
所以,我注意到,有没有实施歪斜广义t分布在scipy。将这个分布拟合到我拥有的一些数据对我来说很有用。不幸的fit是,在这种情况下对我来说似乎不起作用。为了进一步解释,我已经像这样实现了
import numpy as np
import pandas as pd
import scipy.stats as st
from scipy.special import beta
class sgt(st.rv_continuous):
def _pdf(self, x, mu, sigma, lam, p, q):
v = q ** (-1 / p) * \
((3 * lam ** 2 + 1) * (
beta(3 / p, q - 2 / p) / beta(1 / p, q)) - 4 * lam ** 2 *
(beta(2 / p, q - 1 / p) / …Run Code Online (Sandbox Code Playgroud) 假设我有一个100000 x 100的矩阵
import numpy as np
mat = np.random.randint(2, size=(100000,100))
Run Code Online (Sandbox Code Playgroud)
我希望遍历此矩阵,并且如果每个矩阵都row完全包含1或0,则希望将state变量更改为该值。如果状态未更改,则希望设置的整个row值state。的初始值为state0。
天真的for循环可以做到如下
state = 0
for row in mat:
if set(row) == {1}:
state = 1
elif set(row) == {0}:
state = 0
else:
row[:] = state
Run Code Online (Sandbox Code Playgroud)
然而,当矩阵的大小增加时,这花费了不切实际的时间。有人numpy可以向我指出如何利用该循环矢量化并加快速度的方向吗?
所以对于样本输入
array([[0, 1, 0],
[0, 0, 1],
[1, 1, 1],
[0, 0, 1],
[0, 0, 1]])
Run Code Online (Sandbox Code Playgroud)
在这种情况下,预期输出为
array([[0, 0, 0],
[0, 0, 0],
[1, 1, 1],
[1, …Run Code Online (Sandbox Code Playgroud) 我希望有效地使用pandas(或numpy) 而不是for带有if语句的嵌套循环来解决特定问题。这是一个玩具版本:
假设我有以下两个 DataFrame
import pandas as pd
import numpy as np
dict1 = {'vals': [100,200], 'in': [0,1], 'out' :[1,3]}
df1 = pd.DataFrame(data=dict1)
dict2 = {'vals': [500,800,300,200], 'in': [0.1,0.5,2,4], 'out' :[0.5,2,4,5]}
df2 = pd.DataFrame(data=dict2)
Run Code Online (Sandbox Code Playgroud)
现在我希望循环遍历每个数据帧的每一行,并在满足特定条件时将值相乘。这段代码适用于我想要的
ans = []
for i in range(len(df1)):
for j in range(len(df2)):
if (df1['in'][i] <= df2['out'][j] and df1['out'][i] >= df2['in'][j]):
ans.append(df1['vals'][i]*df2['vals'][j])
np.sum(ans)
Run Code Online (Sandbox Code Playgroud)
然而,显然这是非常低效的,实际上我的 DataFrame 可能有数百万个条目,这使得它无法使用。我也不是在创造pandas或numpy高效的向量实现。有谁知道如何有效地矢量化这个嵌套循环?
我觉得这段代码类似于矩阵乘法,所以可以利用它取得进展outer吗?这是if我发现很难融入的情况,因为if逻辑需要将 …
python ×5
numpy ×4
pandas ×3
optimization ×2
performance ×1
scipy ×1
series ×1
statistics ×1
time-series ×1