在不使用数据库软件的情况下从表中获取项目列表

时间:2012-12-04 22:33:53

标签: python sql linux bash bioinformatics

我想在桌子上做一些简单的数据库操作而不用费心去打扰数据库软件,例如,我可以使用GitHub的“filo”包来做类似“groupby”的功能。我想知道是否有类似的东西可以实现一些简单的“加入”功能?或者我可以用Python或Bash做到吗?具体来说,我有一个像这样的表:

Col5a2  NM_007737   chr1    -   45447828    45447829
Slc40a1 NM_016917   chr1    -   45870140    45870141
Gm3852  NM_001177356    chr1    -   45956809    45956810
Slc39a10    NM_172653   chr1    -   46798055    46798056
Obfc2a  NM_028696   chr1    -   51422944    51422945
Myo1b   NM_001161817,NM_010863  chr1    -   51860519    51860520
.
.
.

我有一个清单

Slc40a1
Myo1b
Col5a2
Obfc2a
.
.
.

我想从表中获取列表中的项目,以便我得到:

Slc39a10    NM_172653   chr1    -   46798055    46798056
Myo1b   NM_001161817,NM_010863  chr1    -   51860519    51860520
Col5a2  NM_007737   chr1    -   45447828    45447829
Obfc2a  NM_028696   chr1    -   51422944    51422945
.
.
.

5 个答案:

答案 0 :(得分:3)

这是使用awk的一种方式:

awk 'FNR==NR { a[$1]=$0; next } $1 in a { print a[$1] }' table list

或格式化:

awk 'FNR==NR { a[$1]=$0; next } $1 in a { print a[$1] }' table list | column -t

结果:

Slc40a1  NM_016917               chr1  -  45870140  45870141
Myo1b    NM_001161817,NM_010863  chr1  -  51860519  51860520
Col5a2   NM_007737               chr1  -  45447828  45447829
Obfc2a   NM_028696               chr1  -  51422944  51422945

说明:

  

'FNR == NR {...}'是一个条件,仅对参数列表中的第一个文件为真。

     
    

因此对于名为'table'的文件中的每一行,第一列($ 1)被添加到一个数组(称为'a')中,并为其分配整行的值($ 0)。 'next'然后跳到代码的其余部分并跳转到下一行输入,直到'table'文件中的所有行都被处理完毕。

  
     

'a'中的$ 1是另一个条件。

     
    

这是在询问'list'文件的第一列是否是数组中的键。如果是,则打印出我们刚刚存储在数组中的第一列的值(a [$ 1])。

  

答案 1 :(得分:3)

您确实可以使用两个标准的unix工具join(1)sort(1)来实现这一目标:

$ join <(sort table) <(sort list)

Col5a2 NM_007737 chr1 - 45447828 45447829
Myo1b NM_001161817,NM_010863 chr1 - 51860519 51860520
Obfc2a NM_028696 chr1 - 51422944 51422945
Slc40a1 NM_016917 chr1 - 45870140 45870141

需要拨打sort,因为(来自join man page):

  

重要说明:必须在连接字段上对FILE1和FILE2进行排序。例如,如果'join'没有选项,则使用'sort -k 1b,1'。注意,比较遵守'LC_COLLATE'指定的规则。如果输入未排序且某些行无法连接,则会给出警告消息。

更新:灵感来自this answer的解决方案,保持秩序:

$ join -1 2 <(cat -n list | sort -k2,2) <(sort table) | sort -nk2,2 | cut -d\  -f1,3-

答案 2 :(得分:1)

如果你只是在表的第一列进行非常简单的查找,那么python dict可能就足够了。

像这样构建:

table = {}
with open(table_file) as f:
    for line in f:
        row = line.split()
        table[row[0]] = row

然后,您可以使用列表理解对此词典进行“加入”:

results = [table[key] for key in keys_list]

或者,如果您的第二个列表也是数据文件,则可以改为:

with open(second_file) as f:
    results = [table[line.strip] for line in f]

答案 3 :(得分:0)

import numpy as np
data = []
with open("file1.txt") as f:  #the data file
   for row in f:
      data.append(row.split())
with open("file2.txt") as f:  #the keys file
   keys = map(str.strip,f.readlines())
np_data = np.array(data,np.str)
mask = np.in1d(np_data[:,0],keys)
print np_data[mask]

如果我真的不想使用数据库,那该怎么做呢

答案 4 :(得分:0)

您可以使用像数据库一样工作的pandas来“选择”和转动。这是一个有效的例子:

import pandas as pd
data = pd.DataFrame({ 
        'Col5a2'  : ['NM_007737',    '-',         'chr1', 45447828, 45447829],
        'Slc40a1' : ['NM_016917',    '-',         'chr1', 45870140, 45870141],
        'Gm3852'  : ['NM_001177356', '-',         'chr1', 45956809, 45956810],
        'Slc39a10': ['NM_172653',    '-',         'chr1', 46798055, 46798056],
        'Obfc2a'  : ['NM_028696',    '-',         'chr1', 51422944, 51422945],
        'Myo1b'   : ['NM_001161817', 'NM_010863', 'chr1', 51860519, 51860520],
    })
data.get(['Slc40a1', 'Myo1b', 'Col5a2', 'Obfc2a'])

# Output:

     Slc40a1         Myo1b     Col5a2     Obfc2a
0  NM_016917  NM_001161817  NM_007737  NM_028696
1          -     NM_010863          -          -
2       chr1          chr1       chr1       chr1
3   45870140      51860519   45447828   51422944
4   45870141      51860520   45447829   51422945