2017-06-22 18 views
3

特定の列に文字列を含むcsvファイルと、その他の値を含むCSVファイルがあります。私は弦のリストも持っています。 回線を循環するので、リスト内の文字列の1つがcsvファイルの行に正確に含まれているかどうか確認したいと思います。 この場合は、この行を新しいcsvファイルに書き込む必要があります。私はそれが正常に動作しますが、それは、文字列の「正確な」マッチングを考慮していない、このコードを書いたPython 2.7 CSVファイルの行に完全な文字列を一致させる

22/06/2017 04:00:32 | string1 | value1 
22/06/2017 04:00:32 | string11 | value2  
22/06/2017 04:00:32 | string2 | value3 
22/06/2017 04:00:32 | string3 | value4 

csvファイルは次のように行のリストです。

import os, csv 

def filter_csv(folderpath): 

    list1 = [ 
    ('name1',1,'string1','value1'), 
    ('name2',2,'string2','value2'), 
    ('name3',3,'string3','value3'), 
    ('name4',4,'string4','value4'), 
    ... 
    ] 

    def column(matrix, i): 
     return [row[i] for row in matrix] 

    col = column(list1,2) 

    for file in os.listdir("%s" % folderpath): 
     if file.endswith(".csv"): 
      new_file = 'new_'+file 
      filepath = os.path.join("%s" % folderpath, file) 
      new_filepath = os.path.join("%s" % folderpath, new_file) 

      with open('%s' % filepath) as csvfile: 
       lines = csvfile.readlines() 

      with open('%s' % new_filepath, 'wb') as csvfile2: 
       for line in lines: 
        for namevar in col: 
         if namevar in line: 
          csvfile2.write(line) 

    return 

csvファイルの列に正確に一致する文字列を追加するにはどうすればよいですか?

+0

.split()かのものを使用することはありません - それは常にCSVモジュールを使用してCSVファイルを解析セット

  • にリストを回す:そこCSVであれば"string1"は "string111"に含まれているため、新しいcsvファイルに書き込む "string111"ですが、私はそうしたくありません。最初のcsvに "string1"がある場合のみ、新しいcsvファイルに書き込みたいファイル。 – giube

  • +0

    csvファイルは、行のリストです。22/06/2017 04:00:32 |文字列1 |価値1 – giube

    答えて

    0

    別のライブラリを使って少し違う解決策を提示するだけですが、これは残念だと思いますが、好きかもしれません:)コードに挿入する例を変更できるはずです。 。

    import pandas as pd 
    
    # Dummy col 
    col = ["string1", "string2", "string3"] 
    
    # Read in CSV file 
    df = pd.read_csv("test.csv", header=None, skipinitialspace=True, delimiter ="|") 
    
    # Strip all strings so that trailing whitespace is ignored. 
    # csv library OP used would also be "fooled" by whitepace 
    df_obj = df.select_dtypes(['object']) 
    df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip()) 
    
    # Select only rows with any column that has a value in col 
    df = df[df.isin(col).any(axis=1)] 
    
    # Write out CSV to new file 
    df.to_csv("test2.csv") 
    

    これはcolの値のいずれかの各列をチェックすることにより、CSVの各行をフィルタリングします。いずれかの列の値がcolの場合、出力CSVファイルに表示されます。

    私が見つけた1つのことは、CSVのテキストの末尾に空白がある場合、完全一致が機能しないことでした。たとえば、string1以下のCSV行では、末尾の空白のため完全一致ではありません。

    value1, value2, string1 , value3 
    

    したがって、すべての文字列をトリムする余分なコード。 csvライブラリを使用してテストした場合、同じ問題が発生します。 CSV文字列に空白がないことがわかっている場合は、その2行を削除することもできます。そして、フィルタ処理するコードは、完全な形あなたの例では、(Tomalak's use of globを借りて)次のようになります。

    import pandas as pd 
    import glob 
    import os 
    
    def filter_csv(folderpath): 
    
        list1 = [ 
         ('name1',1,'string1','value1'), 
         ('name2',2,'string2','value2'), 
         ('name3',3,'string3','value3'), 
         ('name4',4,'string4','value4') 
        ] 
    
        def column(matrix, i): 
         return [row[i] for row in matrix] 
    
        col = column(list1,2) 
    
        for filepath in glob.glob("%s/*.csv" % folderpath): 
         filename = os.path.basename(filepath) 
         new_filepath = os.path.join(folderpath, 'new_' + filename) 
         df = pd.read_csv(filename, header=None, skipinitialspace=True, delimiter ="|") 
         df_obj = df.select_dtypes(['object']) 
         df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip()) 
         df[df.isin(col).any(axis=1)].to_csv(new_filepath, sep="|", header=False, index=False) 
    

    しかし、空白が問題ではない場合、あなたはコードのうち、次の行トリミングすることができます:

    df_obj = df.select_dtypes(['object']) 
    df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip()) 
    
    +0

    素晴らしい!これは動作します!単に引数sep = ';'を追加するだけです。 – giube

    1

    フィルタリングされたリストをファイルに書き込むことです。

    フィルタ条件はです。 "CSVラインには事前定義された有効値の1つが必要です"とこれにセット交差点を使用できます。有効な値が必要ですが、現在の入力行と交差し、現在の入力行が残っている場合は残りの値が渡されます。

    import os, csv 
    from glob import glob 
    
    def filter_csv(folderpath): 
    
        list1 = [ 
         ('name1',1,'string1','value1'), 
         ('name2',2,'string2','value2'), 
         ('name3',3,'string3','value3'), 
         ('name4',4,'string4','value4'), 
         # ... 
        ] 
    
        # prepare a set of valid values 
        valid_values = {row[2] for row in list1} 
    
        for filepath in glob("%s/*.csv" % folderpath): 
         filename = os.path.basename(filepath) 
         new_filepath = os.path.join(folderpath, 'new_' + filename) 
    
         with open(filepath, newline='') as infile, \ 
          open(new_filepath, 'wb') as outfile: 
    
          reader = csv.reader(infile) 
          writer = csv.writer(outfile) 
          filtered_rows = (row for row in reader if valid_values.intersection(row)) 
    
          writer.writerows(filtered_rows) 
    

    ノート

    • ​​3210延長
    • withでファイルを見つけることあなたが
    • セットが最適化されている複数の行にまたがる\を使用することができます複数のリソース
    • を扱うことができるため非常に便利です一致する値を検索する場合
    • { ... }は、設定された理解である - 私は意味マッチング「正確な」という
    • よう
    +0

    それは動作しません、私はglob()で行にいくつかの間違いがあると思います。 – giube

    +0

    「働かない」以上のものを私に与えてください。 – Tomalak

    +0

    \ * sigh \ *、 'in'キーワードがありませんでした。 – Tomalak

    関連する問題