【问题标题】:How to remove a specific string common in multiple lines in a CSV file using python script?如何使用 python 脚本删除 CSV 文件中多行中常见的特定字符串?
【发布时间】:2015-07-06 06:49:47
【问题描述】:

我有一个 csv 文件,其中包含 65000 行(大小约为 28 MB)。在每一行中,都给出了开头的特定路径,例如"c:\abc\bcd\def\123\456"。现在假设路径"c:\abc\bcd\" 在所有行中都是通用的,其余内容不同。我必须使用 python 脚本从所有行中删除公共部分(在本例中为 "c:\abc\bcd\")。例如CSV文件的内容如前所述。

C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.frag                   0   0   0
C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.vert                   0   0   0
C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.link-link-0.frag       16  24  3
C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.link-link-0.vert       87  116 69
C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.link-link-0.vert.bin   75  95  61
C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.link-link-0            0   0
C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.link-link-6            0   0   0 

在上面的例子中,我需要如下输出

FILE0.frag                  0   0   0
FILE0.vert                  0   0   0
FILE0.link-link-0.frag      17  25  2
FILE0.link-link-0.vert      85  111 68
FILE0.link-link-0.vert.bin  77  97  60
FILE0.link-link-0               0   0
FILE0.link                  0   0   0

你们中的任何人都可以帮我解决这个问题吗?

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 删除最后一个反斜杠之前的所有字符怎么样?
  • 从问题中不清楚“常见”部分是否要自动检测?
  • 嗨阿维纳什。感谢您的回复。我是 python 新手,并试图了解 python 如何处理文件。由于必须对目录和子目录中的多个文件执行此操作,因此我为此使用 os.walk。
  • Henrik,如果我们将公共部分存储在某个变量中怎么样,因为它总是相同的?

标签: python regex csv


【解决方案1】:
^\S+/

您可以简单地在每一行上使用此正则表达式并替换为empty string。参见演示。

https://regex101.com/r/cK4iV0/17

import re
p = re.compile(ur'^\S+/', re.MULTILINE)
test_str = u"C:/Abc/Def/Test/temp/test/GLNext/FILE0.frag                   0   0   0\nC:/Abc/Def/Test/temp/test/GLNext/FILE0.vert                   0   0   0\nC:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-0.frag       16  24  3\nC:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-0.vert       87  116 69\nC:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-0.vert.bin   75  95  61\nC:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-0            0   0\nC:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-6            0   0   0 "
subst = u" "

result = re.sub(p, subst, test_str)

【讨论】:

    【解决方案2】:

    诸如此类的东西,

    import csv
    
    with open("file.csv", 'rb') as f:
        sl = []
        csvread = csv.reader(f, delimiter=' ')
        for line in csvread:
            sl.append(line.replace("C:/Abc/Def/Test/temp\.\test\GLNext\", ""))
    

    要将列表sl 写到filenew 使用,

    with open('filenew.csv', 'wb') as f:
        csvwrite = csv.writer(f, delimiter=' ')
        for line in sl:
            csvwrite.writerow(line)
    

    【讨论】:

    • 感谢 Ed 的回复。它也会保存文件吗?
    • 您将在 sl 中获得一个新字符串列表。需要调用写。如果您的文件是 csv(带有分隔符,与上面的数据不同),那么您应该使用 csv.reader 和 csv.writer。
    【解决方案3】:

    您可以自动检测公共前缀,而无需对其进行硬编码。你真的不需要regex。 os.path.commonprefix可以使用 而是:

    import csv
    import os
    
    with open('data.csv', 'rb') as csvfile:
        reader = csv.reader(csvfile)
        paths = [] #stores all paths
        rows = [] #stores all lines
        for row in reader:
            paths.append(row[0].split("/")) #split path by "/"
            rows.append(row)
    
        commonprefix = os.path.commonprefix(paths) #finds prefix common to all paths
    
        for row in rows:
            row[0] = row[0].replace('/'.join(commonprefix)+'/', "") #remove prefix
    

    rows 现在有一个可以写入文件的列表列表

    with open('data2.csv', 'wb') as csvfile:
        writer = csv.writer(csvfile)
        for row in rows:
            writer.writerow(row)
    

    【讨论】:

      【解决方案4】:

      以下 Python 脚本将读取您的文件(假设它看起来像您的示例)并将创建一个删除公共文件夹的版本:

      import os.path, csv
      
      finput = open("d:\\input.csv","r")
      csv_input = csv.reader(finput, delimiter=" ", skipinitialspace=True)
      csv_output = csv.writer(open("d:\\output.csv", "wb"), delimiter=" ")
      
      # Create a set of unique folder names
      
      set_folders = set()
      
      for input_row in csv_input:
          set_folders.add(os.path.split(input_row[0])[0])
      
      # Determine the common prefix
      
      base_folder = os.path.split(os.path.commonprefix(set_folders))[0]
      nprefix = len(base_folder) + 1
      
      # Go back to the start of the input CSV 
      
      finput.seek(0)
      
      for input_row in csv_input:
          csv_output.writerow([input_row[0][nprefix:]] + input_row[1:])
      

      使用以下内容作为输入:

      C:/Abc/Def/Test/temp/test/GLNext/FILE0.frag                   0   0   0
      C:/Abc/Def/Test/temp/test/GLNext/FILE0.vert                   0   0   0
      C:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-0.frag       16  24  3
      C:/Abc/Def/Test/temp/test/GLNext2/FILE0.link-link-0.vert       87  116 69
      C:/Abc/Def/Test/temp/test/GLNext5/FILE0.link-link-0.vert.bin   75  95  61
      C:/Abc/Def/Test/temp/test/GLNext7/FILE0.link-link-0            0   0
      C:/Abc/Def/Test/temp/test/GLNext/FILE0.link-link-6            0   0   0
      

      输出如下:

      GLNext/FILE0.frag 0 0 0
      GLNext/FILE0.vert 0 0 0
      GLNext/FILE0.link-link-0.frag 16 24 3
      GLNext2/FILE0.link-link-0.vert 87 116 69
      GLNext5/FILE0.link-link-0.vert.bin 75 95 61
      GLNext7/FILE0.link-link-0 0 0
      GLNext/FILE0.link-link-6 0 0 0
      

      每列之间有一个空格,虽然这很容易改变。

      【讨论】:

        【解决方案5】:

        所以我尝试了类似的方法

        for dirName, subdirList, fileList in os.walk(Directory):
            for fname in fileList:
                if fname.endswith('.csv'):
                    for line in fileinput.input(os.path.join(dirName, fname), inplace = 1):
                        location = line.find(r'GLNext')
                        if location > 0:
                            location += len('GLNext')
                            print line.replace(line[:location], ".")
                        else:
                            print line
        

        【讨论】:

          【解决方案6】:

          您可以为此使用pandas 库。这样做,您可以利用 pandas' 对大型 CSV 文件(甚至数百 MB)的惊人处理。

          代码:

          import pandas as pd
          
          csv_file = 'test_csv.csv'
          df = pd.read_csv(csv_file, header=None)
          print df
          print "-------------------------------------------"
          
          path = "C:/Abc/bcd/Def/Test/temp/test/GLNext/"
          df[0] = df[0].replace({path:""}, regex=True)
          
          print df
          # df.to_csv("truncated.csv") # Export to new file.
          

          结果:

                                                             0   1    2   3
          0    C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.frag   0    0   0
          1    C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.vert   0    0   0
          2  C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.lin...  16   24   3
          3  C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.lin...  87  116  69
          4  C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.lin...  75   95  61
          5  C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.lin...   0    0 NaN
          6  C:/Abc/bcd/Def/Test/temp/test/GLNext/FILE0.lin...   0    0   0
          -------------------------------------------
                                      0   1    2   3
          0                  FILE0.frag   0    0   0
          1                  FILE0.vert   0    0   0
          2      FILE0.link-link-0.frag  16   24   3
          3      FILE0.link-link-0.vert  87  116  69
          4  FILE0.link-link-0.vert.bin  75   95  61
          5           FILE0.link-link-0   0    0 NaN
          6           FILE0.link-link-6   0    0   0
          

          【讨论】:

            猜你喜欢
            • 2015-06-21
            • 2023-01-09
            • 2019-12-13
            • 1970-01-01
            • 1970-01-01
            • 2016-11-14
            • 1970-01-01
            • 1970-01-01
            • 2023-01-19
            相关资源
            最近更新 更多