Pandas:グループ毎に括って最大の値を含む列を抜き出す
PythonのライブラリーであるPandasを使って,「グループ毎に括って最大の値を含む列を抜き出す」方法のメモです.
対象とするのはこんなデータ
Sensor Time Value 0 T-A 10:00:00 25 1 T-B 10:00:01 30 2 T-C 10:00:02 104 3 T-B 10:00:03 52 4 T-C 10:00:04 41 5 T-A 10:00:05 91 6 T-C 10:00:06 102 7 T-B 10:00:07 40 8 T-B 10:00:08 101 9 T-C 10:00:09 97
3種類のSensorから時間と検知された値(Value)が返ってきます.
Sensorの種類ごとに括って,その中で最大の値を出す時間(と言うか行)を抜き出す,というのが今回の狙いです.
コードは下記の通り.
特定の列に含まれる最大値を含む行を抜き出す(日本語が複雑・・)方法が分からなかったのでやや力技を使いました.
import pandas as pd # データ生成 df = pd.DataFrame( {'Time': ['10:00:00', '10:00:01', '10:00:02', '10:00:03', '10:00:04','10:00:05', '10:00:06', '10:00:07', '10:00:08', '10:00:09'], 'Sensor': ['T-A', 'T-B', 'T-C', 'T-B', 'T-C', 'T-A', 'T-C', 'T-B' ,'T-B' ,'T-C'], 'Value': [25, 30, 104, 52, 41, 91, 102, 40 ,101 ,97]}) # datetime型に変換 df['Time'] = df['Time'].apply(lambda dd: pd.to_datetime(dd)) # 'Sensor'で括る df_g = df.groupby('Sensor') # 'Sensor'でくくられたデータフレームの中で'Value'に最大値を含む行を抜き出す def select(xx): # 'Value'に最大値を含む行を抜き出す(そういうメソッドがあるのかもしれないけど分からなかった) val_r = xx[xx['Value'] == max(xx['Value']) ] # 全く同じ行があった場合は削除(このデータの場合は無いですけど) val_r = val_r.drop_duplicates() return val_r df_new = df_g.apply(select)
ご覧の通り,Valueに含まれる最大値を含む行は無理やり書きました.
結果は下記の通り
Sensor Time Value Sensor T-A 5 T-A 2017-10-08 10:00:05 91 T-B 8 T-B 2017-10-08 10:00:08 101 T-C 2 T-C 2017-10-08 10:00:02 104
Anacondaをインストールしようとすると「Failed to create Anaconda menus」と言われる
Anacondaをアップデートしたらおかしくなったので再インストールした.
そしたら「Failed to create Anaconda menus」と言われてインストールできない.
アンインストールしてもフォルダが残っていたので削除したらインストールできたっぽい
Python:秒数が小数点以下のパース
Pandasでデータフレームに格納するときに,時間にナノ秒まで含まれている時のパースのやり方についてのメモ.
対象とするのはこんなデータ.
//file.csv 17:22:59.703371360,10 17:22:59.788956621,20 17:22:59.790719017,30 17:22:59.813919277,20 17:22:59.891942610,10 17:22:59.898820371,20 17:22:59.919604329,30
こんな感じで,小数点以下がすごい長いデータをパースしたいわけです.
一例としてこんな感じでしょうか.
import pandas as pd # データ読み込み df = pd.read_csv('file.csv', names=('time', 'val')) # datetime型に変換 from dateutil import parser df.time = df.time.apply(lambda x: parser.parse(x)) # 表示 print(df.dtypes)
出力すると
time datetime64[ns] val int64 dtype: object
parserを使って無理やりdatetime型に変えています.
あとはapplyで一行づつ適用してます.
若干力技な気がしますが...
追記
このフォーマットの場合はparse_datesで指定するだけでも行けるっぽい.
import pandas as pd # データ読み込み df = pd.read_csv('time.csv', names=('time', 'val'),parse_dates=['time']) # 表示 print(df.dtypes)
ランダム関数について
numpyランダム関数を色々使ってみました.
まずはインポート
In [1]: import numpy as np
random()は0から1までの値が得られる
In [10]: np.random.random() Out[10]: 0.45226808024834264
引数を入れると,入れた数字分の乱数が得られる
In [12]: np.random.random(5) Out[12]: array([ 0.93385679, 0.6383795 , 0.20373784, 0.76812241, 0.42309771])
範囲指定は出来ないみたいです
In [13]: random.uniform(1,100) Traceback (most recent call last):
random.uniformで値を指定できるみたいです
In [14]: np.random.uniform(1,100) Out[14]: 8.543481477277378 In [17]: np.random.uniform(2,5) Out[17]: 2.2877891814898934
引数を入れないとrandom()と同じなんですかね?
In [15]: np.random.uniform() Out[15]: 0.4615576165499794
範囲を指定して,個数も指定できるみたいです
In [18]: np.random.uniform(2,5,3) Out[18]: array([ 4.67283745, 2.26006292, 4.18645001])
Jupyterでmatplotlibのメイリオを使うとしたらエラーが出た
表題のような現象が見られたので,次のように書き換えてみた
import matplotlib import matplotlib.pyplot as plt plt.style.use('ggplot') # ggplotを使う matplotlib.rc('font', family='sans-serif')
移動平均を計算しようとすると「FutureWarning: pd.rolling_mean is deprecated for Series and will be removed in a future version, replace with ・・・」と出て来る
FutureWarning: pd.rolling_mean is deprecated for Series and will be removed in a future version, replace with ・・・
特定の行・列を残す:Python,Numpy
Pandasで条件を指定して行・列を抜き出すやつが有ると思います.正式名称は分かりませんが,df[val>0]みたいなやつです.Numpyのarrayでおんなじことが出来るか試したので,メモ書きしておきます.
まずはこんな感じで配列を作ります.そして1個飛ばしで列を獲得できるかやってみます.
In [31]: import numpy as np In [32]: a = np.array([[ 0, 1, 2, 3], ...: [ 4, 5, 6, 7], ...: [ 8, 9, 10, 11], ...: [12, 13, 14, 15]]) In [33]: label = np.array([ 0, 1, 0, 1]) In [34]: mask = (label == 1)
まずは一個飛ばしで列を獲得してみます.
In [35]: a[:,mask] Out[35]: array([[ 1, 3], [ 5, 7], [ 9, 11], [13, 15]])
続いて一個飛ばしで行を獲得してみます.
In [36]: a[mask,:] Out[36]: array([[ 4, 5, 6, 7], [12, 13, 14, 15]])
それでは,一個飛ばしで行と列の両方を獲得するにはどうやるのでしょう?
In [37]: a[mask,mask] Out[37]: array([ 5, 15])
これだと上手く行かないので,次のように書いてみました.
In [38]: a[:,mask][mask,:] Out[38]: array([[ 5, 7], [13, 15]])