加速引用另一个数据帧的进程

2024-10-02 12:34:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我想要一些关于如何优化以下计算的反馈:

我们有一个固定的索引集I和一个lookback。此外,我们还有一个pd.Series index它的回望中值index_MEDIAN,以及一个大数据帧列表。所有系列/数据帧的索引都是I。每个数据帧都有value列。让D就是这样一个数据帧

对于D的每一行,我们在index_MEDIAN中取相应的值m,并对回望窗口中存在的所有值项求和,条件是index系列中的运行值大于m。换句话说,每当索引值大于回望的中值时,我们对D中相应的值行求和

为了更清楚地说明这一点,下面是上述实现的示意图

  def sumvals(x)

      S = (D['value'].loc[x.index] >= self.index_median.loc[x.index[-1]])
 
      return sum(S*(x-self.index_median.loc[x.index[-1]]))

   D['value'].rolling(lookback).apply(sumvals)

数据帧的列表非常庞大,我注意到这种计算这个数量的方法花费了过多的时间。我怀疑这个问题与这个实现大量使用.loc有关。因此

Is there another way to express this solution without having to reference an external Series so much?

无论哪种方式,任何类型的优化建议都是受欢迎的

编辑。下面是一个具有相应计算的示例数据集

lookback = 3
Index = pd.Series([1,-2,8,-10,3,4,5, 10, -20, 3])
Index_median = Index.rolling(lookback).median
Values = pd.Series([1,2,2,3,0,9,10, 8, 20, 9])

的结果计算应产生

0     NaN
1     NaN
2     2.0
3    13.0
4     0.0
5     6.0
6    11.0
7    12.0
8    23.0
9    28.0

例如,第5行中的值为6。为什么?第5行的索引_中值为3。第5行中的3-回望是序列9、0、3。价值观>;=是3和9,所以这包括了第五行3-3+9-3=6的和。同样,最后一行的指数中位数为3。值中的最后三行都大于3,总和为34-3*3=28


Tags: to数据self列表indexvaluelocseries
3条回答
def sumvals(x)
      m =  self.index_median.loc[x.index[-1]]
      condition = (x.index >= m)
      return sum(x[condition]-m)

   D['value'].rolling(lookback).apply(sumvals)

当我们计算回望窗口中所有值项的总和时,不需要将它们与self.index进行比较。同样根据您的描述,如果您采用D中的值行,则您可以

return sum(x[condition])

而是直接

另一个解决方案是,您可以将整个操作转换为numpy,以加快滚动操作。 为此签出numpy_ext

从您的示例数据开始:

df = pd.DataFrame()
df['I'] = pd.Series([1,-2,8,-10,3,4,5, 10, -20, 3])
df['I_median'] = df['I'].rolling(lookback).median()
df['Values'] = pd.Series([1,2,2,3,0,9,10, 8, 20, 9])

现在为“Value”列添加移位列

# add one column for every lookback    
for colno in range(lookback):  

        # shift the column by one and deduct the median
        df['n'+ str(colno)] = df['Values'].shift(colno) - df['I_median']

        # remove all negative numbers (where value is smaller than median)
        df['n'+ str(colno)] = df['n'+ str(colno)].where(df['n'+ str(colno)]> 0, 0)

# sum up across the new columns
df['result'] = df[df.columns[-lookback:]].sum(axis=1)

result包含您的结果并等于

0     0.0
1     0.0
2     2.0
3    13.0
4     0.0
5     6.0
6    11.0
7    12.0
8    23.0
9    28.0
Name: result, dtype: float64

编辑:数据框中不带移位列

df['result'] = 0

for colno in range(lookback):  
        # shift the column by one and deduct the median
        df['temp'] = df['Values'].shift(colno) - df['I_median']

        # remove all negative numbers (where value is smaller than median)
        df['temp'] = df['temp'].where(df['temp']> 0, 0)

        # sum up across the new columns
        df['result'] = df['result'] + df['temp']

演出

  • 数据帧中有1m行
  • 1000回望
lookback = 1000
df = pd.DataFrame()
df['I'] = pd.Series(np.random.randint(0, 10, size=1000000))
df['I_median'] = df['I'].rolling(lookback).median()
df['Values'] = pd.Series(np.random.randint(0, 10, size=1000000))

大约14秒

.loc速度慢,应用速度慢。 在我看来,使用向量化函数和列上的操作,无需逐行应用和loc查找,就可以实现所需的功能

如果没有@Manakin建议的真实数据示例,很难判断。 但是我试着用一个例子来重新创建你的问题,并根据你的描述来解决它

# lookback window    
lookback = 3 

# Fixed Index
I = [5, 2, 1, 4, 2, 4, 1, 2, 1, 10]

# Dataframe with value column, Index added as column for convenience
df = pd.DataFrame({'I': I, 
                   'value':[6,5,4,3,2,1, 2, 3, 4, 5]},
                   index=I)

# Median over lookback window
df['I_median'] = df.I.rolling(lookback).median()

屈服

|    |  I    |  value   | I_median
|  |   -|     |     |
| 5  | 5     | 6        | NaN      |
| 2  | 2     | 5        | NaN      |
| 1  | 1     | 4        | 2.0      |
| 4  | 4     | 3        | 2.0      |
| 2  | 2     | 2        | 2.0      |
| 4  | 4     | 1        | 4.0      |
| 1  | 1     | 2        | 2.0      |
| 2  | 2     | 3        | 2.0      |
| 1  | 1     | 4        | 1.0      |
| 10 | 10    | 5        | 2.0      |

# Check if Index is greater than median
df['I_gt'] = df.I > df.I_median

# set all rows to 0 where median is greater than index
df['filtered_val'] = df.value.where(df.I_gt, 0)

|    | I  | value | I_median | I_gt  | filtered_val |
|  |  |   -|     |   -|       |
| 5  | 5  | 6     | NaN      | False | 0            |
| 2  | 2  | 5     | NaN      | False | 0            |
| 1  | 1  | 4     | 2.0      | False | 0            |
| 4  | 4  | 3     | 2.0      | True  | 3            |
| 2  | 2  | 2     | 2.0      | False | 0            |
| 4  | 4  | 1     | 4.0      | False | 0            |
| 1  | 1  | 2     | 2.0      | False | 0            |
| 2  | 2  | 3     | 2.0      | False | 0            |
| 1  | 1  | 4     | 1.0      | False | 0            |
| 10 | 10 | 5     | 2.0      | True  | 5            |

然后简单地对过滤后的列进行滚动求和

df.filtered_val.rolling(lookback).sum()

相关问题 更多 >

    热门问题