在python中过滤CSV文件

在python中过滤CSV文件,python,csv,formatting,bioinformatics,Python,Csv,Formatting,Bioinformatics,我下载了这个,它创建了一个基因信息的电子表格。重要的是在HLA-*列中有基因信息。如果该基因的分辨率太低,例如DQB1*03,则应删除该行。如果数据分辨率过高,例如DQB1*03:02:01,则需要删除末尾的:01标记。因此,理想情况下,我希望蛋白质的格式是DQB1*03:02,这样它在DQB1*之后有两个级别的分辨率。如何让python查找这些格式,而忽略其中存储的数据。 e、 g. 更新:我引用的已编辑代码 import csv import re import sys csvdictre

我下载了这个,它创建了一个基因信息的电子表格。重要的是在
HLA-*
列中有基因信息。如果该基因的分辨率太低,例如
DQB1*03
,则应删除该行。如果数据分辨率过高,例如
DQB1*03:02:01
,则需要删除末尾的
:01
标记。因此,理想情况下,我希望蛋白质的格式是
DQB1*03:02
,这样它在
DQB1*
之后有两个级别的分辨率。如何让python查找这些格式,而忽略其中存储的数据。 e、 g.

更新:我引用的已编辑代码

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)

这里有一个超简单的过滤器:

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
python script.py
这里有一个超简单的过滤器:

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
python script.py
我想这里有些东西可以满足你的需要。它不像Peter的回答那么简单,因为它使用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)

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

我认为有些事情可以满足你的要求。它不像Peter的回答那么简单,因为它使用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)


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

您尝试过正则表达式来匹配格式吗?这听起来像是可以通过一个映射和一个过滤器,以及一个正则表达式来完成的。正则表达式用于查找模式,映射用于删除:01,过滤器用于删除行。另外,您是否可以提供一小段输入和所需的输出?不是每个人都想浏览链接并通过Excel电子表格来填充这些内容。@user1161318我该如何编写那行正则表达式来完成这项工作?@user1876508:查看此链接,了解Python正则表达式的信息:我可以看到您添加的代码存在一些问题。注意:使用
open()
调用打开两个文件,并在读卡器上使用模式
'rb'
,在编写器上使用模式
'wb'
。在正则表达式上,将
(\w+)
更改为仅
(\w)
。是否尝试使用正则表达式匹配格式?这听起来像是可以通过一个映射和一个过滤器,以及一个正则表达式来完成的。正则表达式用于查找模式,映射用于删除:01,过滤器用于删除行。另外,您是否可以提供一小段输入和所需的输出?不是每个人都想浏览链接并通过Excel电子表格来填充这些内容。@user1161318我该如何编写那行正则表达式来完成这项工作?@user1876508:查看此链接,了解Python正则表达式的信息:我可以看到您添加的代码存在一些问题。注意:使用
open()
调用打开两个文件,并在读卡器上使用模式
'rb'
,在编写器上使用模式
'wb'
。在正则表达式上,将
(\w+)
更改为仅
(\w)
。更简单的方法是只在每一行上执行
l.replace()
。您可以在sys.stdin:中对行使用:
进行迭代。您能告诉我为什么在这里使用
.readlines()
吗?您可以使用
if',DQB1*03',而不是第行:\n print line,
而不是
if line.find(…
。我不知道
03:02
是什么意思,但是如果
12:34
也是可以接受的,那么你可以在正则表达式中使用
\d\d:\d\d
。如果不匹配,你可以使用
或者
如果匹配为无:
而不是
如果匹配==None
。更简单的方法是只做
l.replace()
在每一行上。您可以对sys.stdin:
中的行使用:
进行迭代。您能告诉我为什么在这里使用
.readlines()
吗?您可以使用
if',DQB1*03',不在行:\n print line,
而不是
if line.find(…
。我不知道
03:02
是什么意思,但是如果
12:34
也是可以接受的,那么您可以在正则表达式中使用
\d\d:\d\d
。如果不匹配,您可以使用
如果匹配为无:
而不是
如果匹配==None
。当python解释器调用re.sub时,repl参数给出一个空值单元格。我如何使其保留给定的数据?我可能有DRB1*01:02:02或DQRB*05:03:01或任何其他类型的格式。同样在第1300-1400行之间,程序停止解析数据并输出不相关的信息。让我编辑您的帖子并将代码添加到文章末尾。
\1
r'DQB1*\1:\2'中的ode>\2将保留正则表达式中前两个
(\d\d)
括号组匹配的数字,但是以
DRB1*
DQRB*
开头的值与模式开头的
DQRB
不匹配,因此
re.sub()
call不会对他们做任何事情。这是可以更改的,但您需要更清楚地描述格式(或模式)要更改的数据。我想不出脚本开始执行您在第1300-1400行之间描述的操作的可能原因。您可以使用
print>>sys.stderr,
语句打印调试信息。您应该在问题中添加任何附加代码,而不是我的答案。此外,我还添加了一条语句,其中说明如果rowfields>1400:print>>sys.stderr没有给我任何东西当python解释器调用re.sub时,repl参数给出一个空单元格。我如何使它保留给定的数据?我可能有DRB1