2017-10-19 13 views
2

私はパスのデータフレームを持っています。タスクが別の列パンダループの代わりにベクトル化

import pandas as pd 
import numpy as np 
import os 


df1 = pd.DataFrame({'Path' : ['C:\\Path1' ,'C:\\Path2', 'C:\\Path3']}) 

#for a MVCE use the below commented out code. WARNING!!! This WILL Create directories on your machine. 
#for path in df1['Path']: 
# os.mkdir(r'PUT_YOUR_PATH_HERE\\' + os.path.basename(path)) 

datetime.fromtimestamp(os.path.getmtime('PATH_HERE'))のようなものを使用してフォルダの最終更新時刻を取得することです私は以下で作業を行うことができますが、私は多くのフォルダを持っている場合には、低速ループです:

私はスピードを向上させるために、このプロセスベクタに行くかどう
for each_path in df1['Path']: 
    df1.loc[df1['Path'] == each_path, 'Last Modification Time'] = datetime.fromtimestamp(os.path.getmtime(each_path)) 

os.path.getmtimeシリーズは受け付けておりません。私のようなものを探しています:

df1['Last Modification Time'] = datetime.fromtimestamp(os.path.getmtime(df1['Path']))

+0

'df1 ['Path']。apply(lambda x:datetime.fromtimestamp(os.path.getmtime(x)))'? – Dark

+0

'os.path.getmtime'がシリーズを受け入れることができない場合、放送はできませんので、ベクトル化された解決策を得ることはできません。 – Dark

+0

@Bharathshetty、applyメソッド*は短時間のテストで*高速です。ループごとに約300ms。残念ながら、ベクトル化されていないソリューションが不可能であることを恐れていました。 – MattR

答えて

0

を100パスで動作すると仮定した3つのアプローチを示しています。アプローチ3は厳密には望ましいと思います。

# Data initialisation: 
paths100 = ['a_whatever_path_here'] * 100 
df = pd.DataFrame(columns=['paths', 'time']) 
df['paths'] = paths100 


def fun1(): 
    # Naive for loop. High readability, slow. 
    for path in df['paths']: 
     mask = df['paths'] == path 
     df.loc[mask, 'time'] = datetime.fromtimestamp(os.path.getmtime(path)) 


def fun2(): 
    # Naive for loop optimised. Medium readability, medium speed. 
    for i, path in enumerate(df['paths']): 
     df.loc[i, 'time'] = datetime.fromtimestamp(os.path.getmtime(path)) 


def fun3(): 
    # List comprehension. High readability, high speed. 
    df['time'] = [datetime.fromtimestamp(os.path.getmtime(path)) for path in df['paths']] 


% timeit fun1() 
>>> 164 ms ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

% timeit fun2() 
>>> 11.6 ms ± 67.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

% timeit fun3() 
>>> 13.1 ns ± 0.0327 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) 
+0

#3は私のために働いています。それは私のテストでも最も速いです – MattR

+0

興味深いのは、この同じタイプのロジックを使って、この質問に似た他の機能をテストすることです。 *この特定のシナリオの場合にのみ、より高速です* @Bharathがコメントで述べたapplyメソッドは、他のシナリオでは最も高速です – MattR

0

(あなたがグループごとに一度だけ高価な呼び出しを行っているように)あなたはGROUPBY transformを使用することができます:私は行くよ

g = df1.groupby("Path")["Path"] 
s = pd.to_datetime(g.transform(lambda x: os.path.getmtime(x.name))) 
df1["Last Modification Time"] = s # putting this on two lines so it looks nicer... 
+0

これはPathカラムが繰り返している場合にのみ時間を節約します... –

+0

パスは重複しませんが、また、通常のラムダ式よりも遅いです: 'os.path.getmtime'の周りに' datetime.fromtimestamp() 'を追加してください。そうでないと値は正しくありません – MattR

+0

@AndyHayden OPはすべてのフォルダ – Dark

関連する問題