2016-08-17 8 views
-2

ファイル名のリストをファイル名に基づいてx:yの比率で並べ替える最適化されたアプローチを作成しようとしています。このファイルリストは、os.scandir(より良いパフォーマンス対os.listdir、src:Python Docs scandir)を使用して調達されました。定義済みの比率でファイル名のリストを分割する

例 -

ファイル(拡張子は無視) -

A_1、A_2、... A_10(ここでAは、ファイル名と1であるファイルのサンプル数である)

B_1 、

上B_2、... B_10

とそれでは、xと言ってみましょう:だから3 :yの比率は7です私は70%のファイル名(A_1..A7、B_1..B_7)と30%(A_8-A_10、B_8..B_10)を別々のリストに入れたいと思っています。リスト1のリスト1〜3の7つのファイルに分割されていれば、ファイルはA_1、A_9、A_5などであることを意味します。

このディレクトリは巨大(〜150kファイル)であり、ファイルの種類ごとにサンプルが異なります。つまり、ファイル名がAのファイルに1000個のファイルがあるか、5個しかない可能性があります。また、約400個の固有のファイル名があります。

この現在のソリューションは、ファイル名ごとに正確な比率の目的に反しているため、解決策とは一切呼ばれるべきではありません。現在、fileObjectのリスト(基本的にはAのような名前、1のような番号、A_1のファイル内のデータなど)を全体としてx:yの比率で分割し、使用時にエントリが任意の順序で生成されるという事実を利用していますos.scandir。少なくとも、有効な解決策になる

ratio_number = int(len(list_of_fileObjects) *.7) 
list_70 = list_of_fileObjects[:ratio_number] 
list_30 = list_of_fileObjects[ratio_number:] 

私の第二のアプローチは、各ファイル名を個別にリストを作成することでした(ファイルのリスト全体をソートする必要)、比でそれを分割し、各ファイル名のためにこれを行います。私はこの問題のよりpythonic /エレガントなソリューションを探しています。扱うデータのサイズを考えれば、どんな提案や助けもありがたいです。

+0

なぜダウンボテッドなのかを知ることは何ですか?私はフォーラムには新しく、特にいくつかの研究で質問をし、アプローチを説明することが推奨されるべきです。これは私を悲しんで、さらに悪いのは、コメントを残していない人たちです。 –

答えて

0

私が状況を正しく理解している場合は、各ファイル名接頭辞のファイルと同じ割合でパーティションを作成しようとしています。あなたの現在の方法は、ファイル全体のセットから正しい割合を選択しますが、異なるファイル名の接頭辞を考慮しないため、適切な割合でそれらを取得しない可能性があります(ほとんどの場合、多分近いでしょう)。

第2のアプローチでは、ファイル名を接頭辞で区切り、次に各サブリストを分割することでその問題を回避します。しかし、すべてのプレフィックスを組み合わせたリストを作成したい場合は、別のリストをプレフィックスで区切り、再結合する必要があるため、このアプローチではデータをコピーする時間が無駄になります。

私はあなたがファイル名の上に1つのループで望むことができると思います。ファイル名接頭辞ごとに2つのデータポイントを追跡する必要があります:最初のサンプルで選択したその接頭辞を持つファイルの数と、あなたが見たその接頭辞を持つファイルの総数。

ratio = 0.7 
prefix_dict = {} # values are lists: [number_selected_for_first_list, total_number_seen] 
first_sample = [] # gets a proportion of the files equal to ratio (for each prefix) 
second_sample = [] # gets the rest of the files 

for filename in list_of_files: 
    prefix = filename.split("_", 1)[0] 
    selected_seen = prefix_dict.setdefault(prefix, [0, 0]) 
    selected_seen[1] += 1 

    if selected_seen[0] < round(ratio * selected_seen[1]): 
     first_sample.append(filename) 
     selected_seen[0] += 1 
    else: 
     second_sample.append(filename) 

このコードの唯一のトリッキーな部分はselected_seenリストをフェッチするdict.setdefaultの使用です。要求されたprefixが辞書にまだ存在しない場合は、新しい値([0, 0])がそのキーの下の辞書に追加(および返されます)されます。後のコードはリストを適切に修正します。

不正確な比率をどの程度正確に処理するかによって、ifの条件を少し変更することができます。 roundコール(これは私が最も正確に分割すると思います)を入れましたが、コードはそれなしで(2番目のサンプルに向かって選択をバイアスする)またはselected_seen[0] <= int(ratio * selected_seen[1])(最初のサンプルに向かってバイアスをかけて)で動作します。

各プレフィックスを分割するときに丸めを選択する方法は、別々のプレフィックスがすべて同じ方向にアンバランスになる可能性があることに注意してください。たとえば、10個の接頭辞が10個のファイル(合計100個のファイル)を持っていた場合、7.5の比率は、75と25ではなく80と20のファイルの最終サンプルリストになります。 2(7.5ラウンドアップ)。すべてのファイルにユニークな接頭辞が付いている場合は、最初のサンプルのすべてが終了します。全体のサンプルが適切なサイズであることが非常に重要な場合は、全体的なサンプルサイズに基づいて、アイテムのサンプリングを少しばかげて行う必要があります。

+0

ありがとうございます@Blckknght私は間違いなくこのアプローチをテストし、結果を知って、あなたの助けに感謝し、まだあなたの答えを投票するのに十分なポイントがありません。 –

0

私はこの問題の良い解決策を考え出しました。

all_file_names = {} 

# ObjList is a list of objects but we only need 
# file_name from that object for our solution 

for x in ObjList: 
    if x.file_name not in all_file_names: 
     all_file_names[x.file_name] = 1 
    else: 
     all_file_names[x.file_name] += 1 

trainingData = [] 
testData = [] 
temp_dict = {} 

for x in ObjList: 
    ratio = int(0.7*all_file_names[x.file_name])+1 
    if x.file_name not in temp_dict: 
     temp_dict[x.file_name] = 1 
     trainingData.append(x) 
    else: 
     temp_dict[x.file_name] += 1 
     if(temp_dict[x.file_name] < ratio): 
      trainingData.append(x) 
     else: 
      testData.append(x) 
関連する問題