2017-06-22 89 views
3

我有一个csv文件,其中包含特定列中的字符串和其他值中的其他值。我也有一个字符串列表。 在线上循环,我想检查列表中的一个字符串是否完全包含在csv文件的行中。 如果是,则该行必须写入新的csv文件。Python 2.7匹配CSV文件的行中的精确字符串

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 

我写了这个代码,它工作正常,但它没有考虑串的“精确”匹配。

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

“精确”匹配我的意思是:如果CSV有是“string111”它写入新的csv文件,因为“string1”包含在“string111”中,但我不希望如此,我只想在第一个csv中存在“string1”的情况下写入新的csv文件文件。 – giube

+0

csv文件是行喜欢的列表:22/06/2017 04:00:32 | string1 | value1 – 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文件中。

我发现的一件事是,如果CSV中的文本有尾随空格,完全匹配将无法工作。例如,在string1以下的CSV行中,由于尾随空格而不能完全匹配。

value1, value2, string1 , value3 

因此,修剪所有字符串的额外代码。使用csv库进行测试,它会有同样的问题。如果你知道你的CSV字符串永远不会有尾随空格,那么你甚至可以删除这两行。然后代码过滤,完全形成你的榜样,是(借用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 =';'在行中:df = pd.read_csv(filename,sep =';',header = None,skipinitialspace = True) – giube

1

你想要做的是写一个过滤列表到文件。

过滤条件是“某些预定义的有效值之一必须出现在CSV行”上,我们可以为此设置一个交集。我们需要一组有效值,并且当它们与当前输入行相交并且剩余一些时,则当前输入行通过。

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可以处理多个资源
  • 可以使用\跨越多行
  • 集优化查找文件非常有用用于查找匹配值
  • { ... }是一套理解 - 它变成一个列表转换成一组
  • 始终解析使用CSV模块CSV文件 - 从不使用.split()或类似的东西
+0

它不起作用,我猜在glob()中存在一些错误。 – giube

+0

请给我一些比“不工作”更多的东西。 – Tomalak

+0

\ * sigh \ *,'in'关键字丢失。 – Tomalak