Python 熊猫:当一列达到另一列的某个值时,如何返回行值?

Python 熊猫:当一列达到另一列的某个值时,如何返回行值?,python,python-3.x,pandas,performance,time,Python,Python 3.x,Pandas,Performance,Time,以下是数据示例: 目标: 当运行\u bid\u max大于或等于ask\u price\u target\u good中的值时,创建一个新的时间戳列。然后为运行的\u bid\u min小于或等于询问价格\u目标\u bad时创建一个单独的时间戳列 注意:这将在大量数据上执行,需要尽快计算。我希望我不必通过iterrows() running\u bid\u min和running\u bid\u max使用running.min() 复制下面的数据,然后使用df=pd.read_剪贴板(s

以下是数据示例:

目标:
运行\u bid\u max
大于或等于
ask\u price\u target\u good
中的值时,创建一个新的时间戳列。然后为
运行的\u bid\u min
小于或等于
询问价格\u目标\u bad
时创建一个单独的时间戳列

注意:这将在大量数据上执行,需要尽快计算。我希望我不必通过
iterrows()

running\u bid\u min
running\u bid\u max
使用
running.min()

复制下面的数据,然后使用
df=pd.read_剪贴板(sep=',')

根据你的问题:

运行\u bid\u max
大于 或等于
ask\u price\u target\u good
中的值。然后创建一个单独的 当
运行\u bid\u min
小于或等于时的时间戳列
ask\u price\u target\u bad

问题似乎微不足道:

df['g'] = np.where(df.running_bid_max.ge(df.ask_price_target_good), df['time'], pd.NaT)

df['l'] = np.where(df.running_bid_min.le(df.ask_price_target_bad), df['time'], pd.NaT)
还是我遗漏了什么


更新:在执行上述命令后,您可能需要
ffill
bfill

df['g'] = df['g'].bfill()
df['l'] = df['l'].ffill()
输出,例如
df['g']

0    2019-07-24 08:00:59.058198
1    2019-07-24 08:00:59.058198
2    2019-07-24 08:00:59.058198
3    2019-07-24 08:00:59.058198
4    2019-07-24 08:00:59.058198
5    2019-07-24 08:00:59.058198
6    2019-07-24 08:00:59.058198
7    2019-07-24 08:00:59.058198
8    2019-07-24 08:00:59.058198
9    2019-07-24 08:00:59.058198
10   2019-07-24 08:01:00.802679
11   2019-07-24 08:01:02.781289
12   2019-07-24 08:01:04.645144
13   2019-07-24 08:01:06.491997
14   2019-07-24 08:01:08.586688

我不确定我是否正确理解了你的问题。我在下面提供了以下问题的解决方案:

  • 对于给定的行(我将称之为当前行),我们将保留其时间为的所有行 介于此行时间和此行时间加上5分钟之间
  • 在我们保留的行中,我们搜索
    运行\u bid\u max
    是否可能优于 当前行的
    ask\u price\u target\u good
    列中的值
  • 如果是这样,我们将第一次出现的
    running\u bid\u max
    保持优于
    ask\u price\u target\u good
    当前行
在您的示例中,对于行
0
,我们在
ask\u price\u target\u good
中有
291.46
。在第8行
8
(其时间在距离第0行
0
时间5分钟的时间范围内),我们发现
291.51
(优于
291.46
),因此我们希望将该值保留在第0行
0

必须对
运行的\u bid\u min
执行对称操作,该操作必须测试为低于
询问价格\u目标\u bad

为了解决这个问题,我编写了以下代码。我使用的不是
iterrows
,而是
DataFrame
apply
功能。然而,对于每一行,我需要在搜索可能优于
ask\u price\u target\u good
的行之前,从整个数据帧(5分钟时间窗口)中选择一组行。我希望这将是足够快,如果你有大的数据帧

import numpy as np
import pandas as pd
import datetime as dtm

data = pd.read_csv("data.csv", parse_dates=["time"])

TIME_WINDOW = 5*60

def over_target_good(row, dataframe):
    time_window = dataframe.time <= (row.time
                                     + dtm.timedelta(seconds=TIME_WINDOW))
    window_data = dataframe[time_window]
    over_test = window_data.running_bid_max >= row.ask_price_target_good
    over_data = window_data[over_test]
    if len(over_data) > 0:
        return over_data.running_bid_max[over_data.index[0]]
    return np.NaN

def below_target_bad(row, dataframe):
    time_window = dataframe.time <= (row.time
                                     + dtm.timedelta(seconds=TIME_WINDOW))
    window_data = dataframe[time_window]
    below_test = window_data.running_bid_min <= row.ask_price_target_bad
    below_data = window_data[below_test]
    if len(below_data) > 0:
        return below_data.running_bid_min[below_data.index[0]]
    return np.NaN

print("OVER\n", data.apply(over_target_good, axis=1, args=(data,)) )
print("BELOW\n", data.apply(below_target_bad, axis=1, args=(data,)) )
将numpy导入为np
作为pd进口熊猫
将日期时间导入为dtm
data=pd.read\u csv(“data.csv”,parse\u dates=[“time”])
时间窗口=5*60
def超过目标值良好(行、数据帧):
时间\u窗口=数据帧。时间=行。询问价格\u目标\u良好
over_data=窗口数据[over_测试]
如果len(超过_数据)>0:
返回超过\u数据。运行\u bid\u max[超过\u数据。索引[0]]
返回np.NaN
def低于_目标_坏(行,数据帧):
time\u window=dataframe.time尝试以下方法:

df['g']=np.NaN
df['l']=np.NaN
deep=len(df.index)
irange= np.arange(1,deep)

for i in irange:
    G=df.time[df.running_bid_max.shift(i)-df.ask_price_target_good>=0]
    G.index=G.index-i
    df['g']=df['g'].combine_first(G)

    L=df.time[df.running_bid_min.shift(i)-df.ask_price_target_bad<=0]
    L.index=L.index-i
    df['l']=df['l'].combine_first(L)
df['g']=np.NaN
df['l']=np.NaN
深度=长度(测向索引)
irange=np.arange(1,深)
对于我在伊兰格:
G=df.time[df.running\u bid\u max.shift(i)-df.ask\u price\u target\u good>=0]
G.index=G.index-i
df['g']=df['g']。先合并(g)

L=df.time[df.running\u bid\u min.shift(i)-df.ask\u price\u target\u bad如果您能打印出所需的输出,那就太好了。否则我可能会错过逻辑

如果您正在处理大量数据,则应用*(这将非常节省内存,如果您使用
cytoolz
甚至快2-4倍)

因此,基本上您希望根据一个或另一个条件对数据进行分区:

partitions=toolz.partitionby(lambda x:(x['running\u bid\u max']>=x['ask\u price\u target\u good'))或
(x['running_bid_min']第[0]部分['ask_price_target_good'],
第[0]部分['running_bid_min']>第[0]部分['ask_price_target_bad'])
对于分区中的部分])
还请注意,创建单个
DataFrame
s很容易

info_cols = ['running_bid_max', 'ask_price_target_good', 'running_bid_min', 'ask_price_target_bad', 'time'] 
data_frames = [pandas.DataFrame(_)[info_cols] for _ in partitions]
data_frames
不幸的是,我找不到
DataFrame
的一行代码
pytition\u by
。它肯定藏在某个地方。(但同样,
pandas
通常会将所有数据加载到内存中—如果您想在I/O期间进行聚合,流式传输可能是一种可行的方法。)


*流媒体示例 例如,让我们创建一个简单的
csv
流:

def数据流():
打开('blubb.csv')作为tsfile:
reader=csv.DictReader(tsfile,分隔符='\t')
number_keys=[[uu用于reader.fieldnames中的u,如果!='time']
def更新值(数据项):
对于k in number_键:
数据项[k]=浮动(数据项[k])
返回数据项
对于读取器中的行:
产量更新_值(dict(行))
一次生成一个已处理行:

next(data_stream())

{'time': '2019-07-24T07:59:46.393418',
 'bid_price': 291.1,
 'ask_price': 291.33,
 'running_bid_max': 291.4,
 'running_bid_min': 291.09,
 'ask_price_target_good': 291.53,
 'ask_price_target_bad': 291.13}
目标

运行\u bid\u max
大于或等于
ask\u price\u target\u good
中的值时,创建新的时间戳列。然后为
running\u bid\u min
小于或等于
ask\u price\u target\u bad

试试这个:

import numpy as np

#   Setup conditions
conditions = [
  (df['running_bid_max'] >= df['ask_price_target_good']),
  (df['running_bid_min'] >= df['ask_price_target_bad'])]

#   Setup output (you could insert timestamp var here)
choices = ["Greater", "Lesser"]

#   Apply conditions
df['bid_value'] = np.select(conditions, choices, default='N/A')
希望这有助于提供解决方案:)

您只需使用:

df['time_bid_max_greater'] = df.time[df['running_bid_max'] >= df['ask_price_target_good']]

df['time_bid_min_less'] = df.time[df['running_bid_min'] <= df['ask_price_target_bad']]

df
df['time\u bid\u max\u morer']=df.time[df['runnin]
next(data_stream())

{'time': '2019-07-24T07:59:46.393418',
 'bid_price': 291.1,
 'ask_price': 291.33,
 'running_bid_max': 291.4,
 'running_bid_min': 291.09,
 'ask_price_target_good': 291.53,
 'ask_price_target_bad': 291.13}
import numpy as np

#   Setup conditions
conditions = [
  (df['running_bid_max'] >= df['ask_price_target_good']),
  (df['running_bid_min'] >= df['ask_price_target_bad'])]

#   Setup output (you could insert timestamp var here)
choices = ["Greater", "Lesser"]

#   Apply conditions
df['bid_value'] = np.select(conditions, choices, default='N/A')
df['time_bid_max_greater'] = df.time[df['running_bid_max'] >= df['ask_price_target_good']]

df['time_bid_min_less'] = df.time[df['running_bid_min'] <= df['ask_price_target_bad']]

df
df['g'] = np.where(df.running_bid_max.ge(df.ask_price_target_good), df['time'], pd.NaT)

df['l'] = np.where(df.running_bid_min.le(df.ask_price_target_bad), df['time'], pd.NaT)
 df['g'] = df['g'].fillna(method='bfill')
 df['l'] = df['l'].fillna(method='bfill')