質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

データマイニング

データマイニングは、購買履歴やクレジットカードの利用履歴、電話の通話履歴など企業にある大量のデータを解析して、その中に隠れたパターンやルールを探し出す技術です。DMと略されることもあります。

Q&A

解決済

3回答

1141閲覧

時系列のデータから高速にデータを取り出して結合するには(SQL, pandas)

akirajyunia

総合スコア2

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

データマイニング

データマイニングは、購買履歴やクレジットカードの利用履歴、電話の通話履歴など企業にある大量のデータを解析して、その中に隠れたパターンやルールを探し出す技術です。DMと略されることもあります。

0グッド

0クリップ

投稿2021/08/27 02:04

###前提・実現したいこと
以前も同じような質問をこちらでさせて頂いたのですが、不足があったので、再度皆様のお力を貸して頂ければと思います。
以下のような時系列のデータ(X)があった際に、先頭フラグ(Y)を基準として、そこから何サンプル毎、というような取り出し方をして新しいデータテーブルを作る際に、一発で変換する方法はありますでしょうか。SQL, pandas問いません。現在、for文を用いてstackをしていますが、処理が遅く困っています。また、前回cumsumとheadを使用した方法を教えて頂いたのですが、headでは実現したい処理に少し手が届かなく困っております。

###対象のデータ
X = 256, 250, 240, 230, 240, 244, 250, 260, 255, 264, 222, 243, 255
Y = 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0

Y = 1の位置から5つ毎のデータを取得してテーブルにする

###実現したい変換先データ
X = 256, 250, 240, 230, 240, 240, 244, 250, 260, 255, 260, 255, 264, 222, 243
L = 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3

※Lは新データの番号

###stack思考のコード

Python

1import pandas as pd 2 3X = [256, 250, 240, 230, 240, 244, 250, 260, 255, 264, 222, 243, 255] 4Y = [ 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0] 5 6data = pd.DataFrame() 7data["X"] = X 8data["Y"] = Y 9 10print(data) 11 12newX = [] 13newL = [] 14for label, index in enumerate(data[data["Y"]==1].index): 15 newX.extend(data["X"][index:index+5].values) 16 for i in range(5): 17 newL.append(label) 18 19newData = pd.DataFrame() 20newData["X"] = newX 21newData["L"] = newL 22print(newData)

###headを用いたコード

Python

1import pandas as pd 2 3df = pd.DataFrame({ 4 'X': [256, 250, 240, 230, 240, 244, 250, 260, 255, 264, 222, 243, 255], 5 'Y': [ 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0]}) 6 7df['L'] = (df['Y'] == 1).cumsum() 8 9df_new = df[df['L'] > 0].groupby('L').head(5) ##Lのラベルの範囲を超えているので取得できない

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

SQLでの実装例

■PostgreSQL 9.4 以降

SQL

1SELECT X 2 , (N - 1) / 5 + 1 L -- 「 5 」というマジックナンバーがパラメータ 3 , N -- この列はデモ用に表示させただけで、実際は射影する必要無し 4FROM unnest( 5 -- 先頭フラグ(Y)は不要 6 -- ( X の要素数に応じた結果セットが自動で返ります ) 7 8 -- 配列も実際はパラメータになるでしょう 9 array[256,250,240,230,240,240,244,250,260,255,260,255,264,222,243]::int[] 10 -- 配列は以下のように記述しても可 11 -- '{256,250,240,230,240,240,244,250,260,255,260,255,264,222,243}'::int[] 12) 13with ordinality 14AS 15 db( X, N ) 16;

■結果

XLN
25611
25012
24013
23014
24015
24026
24427
25028
26029
255210
260311
255312
264313
222314
243315

なお、SQLの実行速度については
バージョン 12関数のオプティマイザーサポートが導入されたようなので
投入するデータの件数とバージョン次第で大きな差がありそうです。

また、SQLの実行方法は大きく分けて二通りあるでしょう。

  1. pythonで動的にSQL文を組み立ててDBに直接クエリを投げる
  2. DB側にユーザー定義のstored functionを登録しておいてpythonから呼び出す

以下、PL/PgSQLで記述したストアドのサンプルです

SQL

1/* 2-- 呼び出し例( 使い方 ): 3SELECT get_separate_data( 4 5, 5 array[256,250,240,230,240,240,244,250,260,255,260,255,264,222,243] 6); 7*/ 8CREATE OR REPLACE FUNCTION get_separate_data 9 ( delimiter int, paramarray int[] ) 10 -- 戻り値は CREATE TYPE で定義しても SETOF record と記述してもいいでしょう 11 RETURNS TABLE ( X int, L int ) 12AS 13$$ 14 SELECT X 15 , (N - 1) / $1 + 1 16 FROM 17 unnest ( $2 ) 18 with ordinality 19 AS 20 db( X, N ) 21$$ 22LANGUAGE SQL;

投稿2021/08/27 04:40

mayu-

総合スコア335

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akirajyunia

2021/08/30 05:19

ご回答頂きありがとうございました。ベストアンサーに選ばせて頂きました。 unnestとordinalityを使用すればよかったんですね! ありがとうございました。
bsdfan

2021/08/30 05:26

こちらの回答には、Yに応じてXを作成する部分が入っていないように見えます。 回答には、変換された後のXが埋め込まれているようです。
guest

0

取り出したい行のインデックスを作成してから、一回で取り出せば早くなると思います。

インデックスの計算は、そのほうが簡単にかけるためnumpyを使っています。

python

1import pandas as pd 2import numpy as np 3 4X = [256, 250, 240, 230, 240, 244, 250, 260, 255, 264, 222, 243, 255] 5Y = [ 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0] 6 7data = pd.DataFrame() 8data["X"] = X 9data["Y"] = Y 10 11N = 5 12 13idx0, = np.nonzero(data['Y'].array == 1) 14idx = np.ravel(np.arange(N) + idx0[:, None]) 15 16newData = pd.DataFrame({ 17 'X': data['X'].array[idx], 18 'L': np.arange(len(idx)) // N + 1})

idx0 は numpy.nonzero() で y=1 のインデックス[0, 4, ...]をとりだしていて、
idx は numpy のブロードキャストを使って [0, 1, 2, 3, 4, 4 + 0, 4 + 1, ...] を作っています。

■追記

idxがXの範囲を超える(Y=1のあと5行ない)場合があるケースでは、最後を下記に変更ください。

python

1mask = idx < len(data['X']) 2newData = pd.DataFrame({ 3 'X': data['X'].array[idx[mask]], 4 'L': np.arange(len(idx))[mask] // N + 1})

投稿2021/08/27 03:31

編集2021/08/27 08:20
bsdfan

総合スコア4774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akirajyunia

2021/08/30 05:17

すぐにご回答頂きまして、ありがとうございました。とても助かりました。 重複したindexを先に作ってしまえばよかったのですね。 SQLの方の回答とベストアンサーで大変悩みましたが、SQLの方が一発で出来るので、そちらをベストアンサーにさせて頂きました。高評価は押させて頂きました。ありがとうございました。
guest

0

あまり綺麗ではありませんが、一応動いています。

python

1>>> import pandas as pd 2>>> X = 256, 250, 240, 230, 240, 244, 250, 260, 255, 264, 222, 243, 255 3>>> Y = 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 4>>> N = 5 5>>> 6>>> df = pd.DataFrame({'X': X, 'Y': Y}) 7>>> df2 = pd.concat([df]+[df['X'].shift(-1-i) for i in range(N-1)], axis=1) 8>>> df3 = df2[df2['Y'] == 1].dropna().astype(int) 9>>> df3['L'] = df3['Y'].cumsum() 10>>> df4 = df3.drop('Y', axis=1).set_index('L').stack().reset_index().drop('level_1', axis=1).rename(columns={0:'X'}) 11>>> print(df4) 12 L X 130 1 256 141 1 250 152 1 240 163 1 230 174 1 240 185 2 240 196 2 244 207 2 250 218 2 260 229 2 255 2310 3 260 2411 3 255 2512 3 264 2613 3 222 2714 3 243

投稿2021/08/27 03:12

ppaul

総合スコア24668

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akirajyunia

2021/08/27 08:34

早急なご回答ありがとうございました。df2を出力するところで、concatとfor文を内包表記で書いているのは、とても勉強になりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問