【问题标题】:Filtering a CSV file in python在python中过滤CSV文件
【发布时间】:2023-04-10 02:35:01
【问题描述】:

我已经下载了这个csv file,它创建了一个基因信息电子表格。重要的是在HLA-* 列中,有基因信息。如果基因的分辨率太低,例如DQB1*03 那么该行应该被删除。如果数据分辨率太高,例如DQB1*03:02:01,那么末尾的:01标签需要去掉。因此,理想情况下,我希望蛋白质采用DQB1*03:02 格式,以便在DQB1* 之后具有两个级别的分辨率。我如何告诉 python 寻找这些格式,并忽略其中存储的数据。 例如

if (csvCell is of format DQB1*03:02:01):
   delete the :01 # but do this in a general format
elif (csvCell is of format DQB1*03):
   delete row
else:
   goto next line

更新:我引用的编辑代码

import csv
import re
import sys

csvdictreader = csv.DictReader(open('mhc.csv','r+b'), delimiter=',')
csvdictwriter = csv.DictWriter(file('mhc_fixed.csv','r+b'), fieldnames=csvdictreader.fieldnames, delimiter=',')
csvdictwriter.writeheader()
targets = [name for name in csvdictreader.fieldnames if name.startswith('HLA-D')]

for rowfields in csvdictreader:
  keep = True
  for field in targets:
    value = rowfields[field]
    if re.match(r'^\w+\*\d\d$', value):
      keep = False
      break # quit processing target fields
    elif re.match(r'^(\w+)\*(\d+):(\d+):(\d+):(\d+)$', value):
      rowfields[field] = re.sub(r'^(\w+)\*(\d+):(\d+):(\d+):(\d+)$',r'\1*\2:\3', value)
    else: # reduce gene resolution if too high
              # by only keeping first two alles if three are present
      rowfields[field] = re.sub(r'^(\w+)\*(\d+):(\d+):(\d+)$',r'\1*\2:\3', value)
  if keep:
     csvdictwriter.writerow(rowfields)

【问题讨论】:

  • 您是否尝试过正则表达式来匹配格式?这听起来像是可以通过映射和过滤器,使用正则表达式来完成的事情。用于查找模式的正则表达式,用于删除 :01 的映射和用于删除行的过滤器。
  • 另外,你能提供一个小的输入和所需的输出吗?不是每个人都希望浏览链接并通过 Excel 电子表格进行挖掘以填写内容。
  • @user1161318 我将如何编写这行正则表达式来完成此操作?
  • @user1876508:查看此链接,了解有关 Python 正则表达式的信息:docs.python.org/2/library/re.html
  • 我可以看到您添加的代码存在一些问题。值得注意的是:使用open() 调用打开两个文件,并在阅读器上使用'rb' 模式,在编写器上使用'wb'。在正则表达式中,将 (\w+) 更改为 (\w)。

标签: python csv formatting bioinformatics


【解决方案1】:

这是我认为可以满足您的需求的东西。它不像彼得的回答那么简单,因为它使用 Python 的 csv 模块来处理文件。它可能会被重写和简化,就像他一样将文件视为纯文本,但这应该很容易。

import csv
import re
import sys

csvdictreader = csv.DictReader(sys.stdin, delimiter=',')
csvdictwriter = csv.DictWriter(sys.stdout, fieldnames=csvdictreader.fieldnames, delimiter=',')
csvdictwriter.writeheader()
targets = [name for name in csvdictreader.fieldnames if name.startswith('HLA-')]

for rowfields in csvdictreader:
    keep = True
    for field in targets:
        value = rowfields[field]
        if re.match(r'^DQB1\*\d\d$', value): # gene resolution too low?
            keep = False
            break # quit processing target fields
        else: # reduce gene resolution if too high
              # by only keeping first two alles if three are present
            rowfields[field] = re.sub(r'^DQB1\*(\d\d):(\d\d):(\d\d)$',
                                      r'DQB1*\1:\2', value)
    if keep:
        csvdictwriter.writerow(rowfields)

对我来说最困难的部分是确定你想做什么。

【讨论】:

  • 当python解释器调用re.sub时,repl参数给出一个空单元格。我怎样才能使它保留给定的数据?我可能有 DRB1*01:02:02 或 DQRB*05:03:01 或任何其他此类格式。
  • 同样在第 1300-1400 行之间,程序停止解析数据并输出不相关的信息。让我编辑你的帖子并将我的代码添加到它的末尾。
  • \1 和 \2 中的 r'DQB1*\1:\2' 将保留与正则表达式中前两个 (\d\d) 括号组匹配的数字,但是以 DRB1* 或 DQRB* 开头的值与模式开头的DQRB 不匹配——因此re.sub() 调用不会对它们做任何事情。这可以更改,但您需要更清楚地描述要更改的数据的格式(或模式)。
  • 我想不出脚本在第 1300-1400 行之间开始执行您所描述的操作的可能原因。您可以使用print >>sys.stderr, ... 语句打印调试信息。您应该在您的问题中添加任何其他代码,而不是我的答案。
  • 我还添加了一条语句,说明 if rowfields > 1400: print >>sys.stderr which give me nothing
【解决方案2】:

这是一个超简单的过滤器:

import sys

for line in sys.stdin:
  line = line.replace( ',DQB1*03:02:01,', ',DQB1*03:02,' )

  if line.find( ',DQB1*03,' ) == -1:
    sys.stdout.write( line )

或者,如果你想使用正则表达式

import re
import sys

for line in sys.stdin:
  line = re.sub( ',DQB1\\*03:02:01,', ',DQB1*03:02,', line )
  if re.search( ',DQB1\\*03,', line ) == None:
    sys.stdout.write( line )

运行它

python script.py < data.csv

【讨论】:

  • 更简单的方法是在每一行都输入l.replace()。
  • 您可以使用:for line in sys.stdin: 进行迭代。你能告诉你为什么在这里使用.readlines()吗? I'm interested
  • 您可以使用if ',DQB1*03,' not in line: \n print line, 代替if line.find(...。我不知道03:02 是什么意思,但如果12:34 也可以接受,那么您可以在正则表达式中使用\d\d:\d\d。您可以使用if not match: 或if match is None: 而不是if match == None。
猜你喜欢
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 2018-07-16
  • 2020-09-04
  • 1970-01-01
相关资源
最近更新 更多