以下はデータのサンプルです。
目標:
_running_bid_max
_が_ask_price_target_good
_の値以上の場合の新しいタイムスタンプ列を作成します。次に、_running_bid_min
_が以下_ask_price_target_bad
_の場合に、別のタイムスタンプ列を作成します。
注:これは大量のデータに対して実行され、必要な計算は可能な限り高速に行われます。 iterrows()
を使用してすべての行を反復処理する必要がないことを願っています
_running_bid_min
_および_running_bid_max
_は、将来の特定のタイムフレームからrunning.min()
およびpd.running.max()
を使用して計算されます(この例では5分のタイムラインを使用しています。したがって、実行中の最小、現在の時刻から最大5分になります)
以下のデータをコピーしてから、df = pd.read_clipboard(sep=',')
を使用してください
_ time,bid_price,ask_price,running_bid_max,running_bid_min,ask_price_target_good,ask_price_target_bad
2019-07-24 07:59:44.432034,291.06,291.26,291.4,291.09,291.46,291.06
2019-07-24 07:59:46.393418,291.1,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:48.425615,291.1,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:50.084206,291.12,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:52.326455,291.12,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:54.428181,291.12,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:58.550378,291.14,291.35,291.4,291.2,291.55,291.15
2019-07-24 08:00:00.837238,291.2,291.35,291.4,291.2,291.55,291.15
2019-07-24 08:00:57.338769,291.4,291.46,291.51,291.4,291.66,291.26
2019-07-24 08:00:59.058198,291.4,291.46,291.96,291.4,291.66,291.26
2019-07-24 08:01:00.802679,291.4,291.46,291.96,291.4,291.66,291.26
2019-07-24 08:01:02.781289,291.4,291.46,291.96,291.45,291.66,291.26
2019-07-24 08:01:04.645144,291.45,291.46,291.96,291.45,291.66,291.26
2019-07-24 08:01:06.491997,291.45,291.46,292.07,291.45,291.66,291.26
2019-07-24 08:01:08.586688,291.45,291.46,292.1,291.45,291.66,291.26
_
あなたの質問から:
running_bid_max
がask_price_target_good
の値以上の場合の新しいタイムスタンプ列を作成します。次に、running_bid_min
がask_price_target_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
必要な出力を印刷できれば非常に便利です。さもなければ、私は論理を見逃すかもしれません。
大量のデータで作業している場合、 スチーム分析 *を適用することは理にかなっています。 (これはかなりメモリ効率が良く、cytoolz
を使用すると2〜4倍速くなります)
したがって、基本的には、データをpartitionいずれかの条件に基づいてデータにしたいとします。
partitions = toolz.partitionby(lambda x: (x['running_bid_max'] >= x['ask_price_target_good']) or
(x['running_bid_min'] <= x['ask_price_target_bad']), data_stream)
個々のパーティションで何をするかはあなた次第です(追加のフィールドや列などを作成できます)。
print([(part[0]['time'], part[-1]['time'],
part[0]['running_bid_max'] > part[0]['ask_price_target_good'],
part[0]['running_bid_min'] > part[0]['ask_price_target_bad'])
for part in partitions])
[('2019-07-24T07:59:46.393418', '2019-07-24T07:59:46.393418', False, False),
('2019-07-24T07:59:44.432034', '2019-07-24T07:59:44.432034', False, True),
('2019-07-24T07:59:48.425615', '2019-07-24T07:59:54.428181', False, False),
('2019-07-24T07:59:58.550378', '2019-07-24T08:00:57.338769', False, True),
('2019-07-24T08:00:59.058198', '2019-07-24T08:01:08.586688', True, True)]
また、個別の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
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.4 291.53 291.09 291.13 2019-07-24T07:59:46.393418
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.4 291.46 291.09 291.06 2019-07-24T07:59:44.432034
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.4 291.53 291.09 291.13 2019-07-24T07:59:48.425615
1 291.4 291.53 291.09 291.13 2019-07-24T07:59:50.084206
2 291.4 291.53 291.09 291.13 2019-07-24T07:59:52.326455
3 291.4 291.53 291.09 291.13 2019-07-24T07:59:54.428181
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.40 291.55 291.2 291.15 2019-07-24T07:59:58.550378
1 291.40 291.55 291.2 291.15 2019-07-24T08:00:00.837238
2 291.51 291.66 291.4 291.26 2019-07-24T08:00:57.338769
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.96 291.66 291.40 291.26 2019-07-24T08:00:59.058198
1 291.96 291.66 291.40 291.26 2019-07-24T08:01:00.802679
2 291.96 291.66 291.45 291.26 2019-07-24T08:01:02.781289
3 291.96 291.66 291.45 291.26 2019-07-24T08:01:04.645144
4 292.07 291.66 291.45 291.26 2019-07-24T08:01:06.491997
5 292.10 291.66 291.45 291.26 2019-07-24T08:01:08.586688
残念ながら、ワンライナーが見つかりませんでしたpytition_by
for DataFrame
。きっとどこかに隠されています。 (ただし、pandas
は通常、すべてのデータをメモリにロードします。I/ O中に集約したい場合は、ストリーミングが適しています。)
たとえば、単純なcsv
ストリームを作成してみましょう。
def data_stream():
with open('blubb.csv') as tsfile:
reader = csv.DictReader(tsfile, delimiter='\t')
number_keys = [_ for _ in reader.fieldnames if _ != 'time']
def update_values(data_item):
for k in number_keys:
data_item[k] = float(data_item[k])
return data_item
for row in reader:
yield update_values(dict(row))
一度に1つの処理された行を生成します。
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}
これを試して:
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)
ディープパラメーターを変更できます(時間枠)
最適化できる
私はあなたの問題を正しく理解しているとは思いません。以下の問題の解決策を以下に示します。
running_bid_max
が現在の行のask_price_target_good
列にある値よりも優れているかどうかを検索しますrunning_bid_max
を現在の行のask_price_target_good
よりも上に保持しますあなたの例では、行0
の場合、291.46
にask_price_target_good
があります。行8
(row0
の時間から5分の時間枠内の時間)で291.51
(291.46
より優れている)を見つけ、したがって、この値を行0
に保持します。
対称操作はrunning_bid_min
に対して行う必要があります。これは、ask_price_target_bad
よりも劣るようにテストする必要があります。
この問題を解決するために、次のコードを書きました。私はiterrows
ではなくapply
のDataFrame
関数を使用しています。それにもかかわらず、各行について、ask_price_target_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,)) )
目標
running_bid_max
がask_price_target_good
の値以上の場合の新しいタイムスタンプ列を作成します。次に、running_bid_min
がask_price_target_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['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')
これで、行9の行0のタイムスタンプが得られます。
これはあなたが探しているものですか?