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

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

ただいまの
回答率

89.63%

Python pandas 行番号を基にしたデータ追加について

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 2,106

chiaki38

score 9

環境:Python 2.7.10, pandas:0.18.1

前提・実現したいこと

次のcsvファイルの各行にタイムスタンプを振りたいと考えています.

1行目はデータ計測を開始した時点のタイムスタンプ,
2行目は取得周期,
3行目以降はセンサデータ値となっています.

data.csv

1483805506
64
0.01
-0.03
-0.05
-0.05
0.13
0.36
0.66
・・・

こちらのデータから,
タイムスタンプが1列目,センサデータが2列目になるような形で出力結果を得たいと考えています.

試したこと

これまではタイムスタンプを格納するSeriesを一度作成して読み込んだデータと結合していました.
しかし,データ量が多く処理時間が長過ぎるため,for文を使用しないような方法を取りたいと思っています.

例えば,他の回答者様が提示されている(https://teratail.com/questions/27787)ような方法で,
処理できれば時間短縮になるかと考えているのですが,
行ごとに値を更新するために,行番号を用いて値を計算するといったことは可能なのでしょうか?

ご教授のほどよろしくお願いします.

こちらはこれまで試したソースコードになります.

inputdata = pd.read_csv( data.csv )

tmp_time = inputdata.ix[0, 0]
delta_time = 1 / tmp_time.ix[1, 0]

for num in xrange( inputdata.shape[0] ):
    tmp_time = tmp_time + delta_time

    sr1 = pd.Series( [tmp_time], name='time' )
    sr2 = pd.Series( inputdata.ix[num], index=['data'] )
    sr2 = sr2.append(sr1)

    outputdata = outputdata.append( sr2, ignore_index=True )
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+3

.append()の処理がボトルネックになっていると思われます。

お察しの通り、index(行番号)を元に計算することが可能です。
枠となるシリーズまたはデータフレームを先に作っておき、その中にデータを入れ込む方が一般的には処理が早いです。

元のデータがcsvではなかったため、変数に代入することで代用しました。適宜変更してください。

import pandas as pd

tmp_time = 1483805506
delta_time = 64
inputdata = pd.Series([0.01, -0.03, -0.05, -0.05,  0.13,  0.36,  0.66])

df = pd.DataFrame(inputdata, columns=['data'])
df['time'] = df.index.map(lambda x: tmp_time + delta_time * x)
df = df.reindex_axis(['time' ,'data'], axis=1)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/16 11:38

    ご回答ありがとうございます!参考になりました!

    キャンセル

checkベストアンサー

+1

import datetime as dt
header = pd.read_csv('data.csv', header=None, nrows=2)
inputdata = pd.read_csv( 'data.csv' ,header=None, skiprows=2)
delta_time = 1 / header.ix[1, 0] * 1000

timestamp = pd.DataFrame(pd.date_range(dt.datetime.fromtimestamp(header.ix[0,0]), 
                                       periods=len(inputdata.index),freq=str(delta_time) + 'ms'))

pd.concat([timestamp, inputdata], axis=1)

pandas の date_range を使うと良いと思います。
たぶん、lambdaを使うより、もっと高速かと思われます。

■追記

試しに2万レコードのデータでテストしてみました。

 1. for loopで append した場合

   CPU times: user 22.4 s, sys: 267 ms, total: 22.7 s
   Wall time: 22.9 s


 2. lambda で実行した場合

  CPU times: user 26.6 ms, sys: 16 ms, total: 42.6 ms
  Wall time: 69.1 ms


 3. date_range を使った場合

  CPU times: user 18.1 ms, sys: 5.51 ms, total: 23.6 ms
  Wall time: 26.7 ms

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/16 11:37

    参考になりました!ありがとうございます!

    キャンセル

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

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる