从一个巨大的文件 (70GB) 中有效地删除列中的重复值
Efficiently remove duplicated values within a column from a huge file (70GB)
大家好,我有一个巨大的表格文件 (76GB),我想删除该文件的一些行。
这是头:
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q7PRY1_Anopheles_gambiae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei P25867_Drosophila_melanogaster_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei J3JXP2_Dendroctonus_ponderosae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
我想使用一种有效的方法(我不能使用 pandas 因为加载文件的时间非常长)。
为了在第一列中只保留第一个重复的 2 行。
例如,如果我有一个文件,例如:
注意:table 是 tabular separated
。
示例;
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q7PRY1_Anopheles_gambiae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei P25867_Drosophila_melanogaster_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei J3JXP2_Dendroctonus_ponderosae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A0L7KYD3_Operophtera_brumata_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei Q7PRY1_Anopheles_gambiae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei P25867_Drosophila_melanogaster_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei J3JXP2_Dendroctonus_ponderosae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
预期输出:
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
使用这个 Perl 单行代码:
perl -F'\t' -lane 'print if $seen{ $F[0] }++ < 2' in_file > out_file
示例:
echo 1 2 3 2 3 3 3 3 | xargs -n1 | perl -F'\t' -lane 'print if $seen{ $F[0] }++ < 2'
打印:
1
2
3
2
3
Perl 单行代码使用这些命令行标志:
-e
: 告诉 Perl 查找内联代码,而不是在文件中。
-n
:一次循环输入一行,默认分配给 $_
。
-l
: 在执行内联代码之前去除输入行分隔符(默认情况下在 *NIX 上为 "\n"
),并在打印时附加它。
-a
: 在空格或 -F
选项中指定的正则表达式上将 $_
拆分为数组 @F
。
-F'/\t/'
:在 TAB 上拆分为 @F
,而不是在空格上。
$seen{ $F[0] }++
:将散列%seen
的元素加1,其中键为$F[0]
,第一列的值
另见:
perldoc perlrun
: how to execute the Perl interpreter: command line switches
awk
救援!
如果您的文件按示例排序,则此脚本不会占用任何内存。
如果文件以制表符分隔且第一个字段没有任何空格,则无需指定字段分隔符
$ awk 'p!={c=2; p=} c&&c--' file
每次更改密钥后捕获新密钥并打印 2 行。
我知道 perl 和 awk 版本可以工作,而且很好而且紧凑。如果你想要 python 中的版本,我可能会天真地尝试:
import collections
keys = collections.defaultdict(int)
with open("file_in.txt") as file_in:
with open("file_out.txt", "w") as file_out:
for line in file_in:
key = line.split("\t", 1)[0]
keys[key] += 1
if keys[key] < 3:
file_out.write(line)
大家好,我有一个巨大的表格文件 (76GB),我想删除该文件的一些行。
这是头:
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q7PRY1_Anopheles_gambiae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei P25867_Drosophila_melanogaster_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei J3JXP2_Dendroctonus_ponderosae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
我想使用一种有效的方法(我不能使用 pandas 因为加载文件的时间非常长)。 为了在第一列中只保留第一个重复的 2 行。
例如,如果我有一个文件,例如:
注意:table 是 tabular separated
。
示例;
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q7PRY1_Anopheles_gambiae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei P25867_Drosophila_melanogaster_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei J3JXP2_Dendroctonus_ponderosae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A0L7KYD3_Operophtera_brumata_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei Q7PRY1_Anopheles_gambiae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei P25867_Drosophila_melanogaster_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei J3JXP2_Dendroctonus_ponderosae_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
预期输出:
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009916.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei A0A653DM45_Callosobruchus_maculatus_Insect 100.000 45 0 0 4 48 65 109 1.563E-24 98 110
CM009917.1_1:1212271-1212415(+):Neodiprion_lecontei Q1HR02_Aedes_aegypti_Insect 100.000 45 0 0 4 48 102 146 1.563E-24 98 147
使用这个 Perl 单行代码:
perl -F'\t' -lane 'print if $seen{ $F[0] }++ < 2' in_file > out_file
示例:
echo 1 2 3 2 3 3 3 3 | xargs -n1 | perl -F'\t' -lane 'print if $seen{ $F[0] }++ < 2'
打印:
1
2
3
2
3
Perl 单行代码使用这些命令行标志:
-e
: 告诉 Perl 查找内联代码,而不是在文件中。
-n
:一次循环输入一行,默认分配给 $_
。
-l
: 在执行内联代码之前去除输入行分隔符(默认情况下在 *NIX 上为 "\n"
),并在打印时附加它。
-a
: 在空格或 -F
选项中指定的正则表达式上将 $_
拆分为数组 @F
。
-F'/\t/'
:在 TAB 上拆分为 @F
,而不是在空格上。
$seen{ $F[0] }++
:将散列%seen
的元素加1,其中键为$F[0]
,第一列的值
另见:
perldoc perlrun
: how to execute the Perl interpreter: command line switches
awk
救援!
如果您的文件按示例排序,则此脚本不会占用任何内存。
如果文件以制表符分隔且第一个字段没有任何空格,则无需指定字段分隔符
$ awk 'p!={c=2; p=} c&&c--' file
每次更改密钥后捕获新密钥并打印 2 行。
我知道 perl 和 awk 版本可以工作,而且很好而且紧凑。如果你想要 python 中的版本,我可能会天真地尝试:
import collections
keys = collections.defaultdict(int)
with open("file_in.txt") as file_in:
with open("file_out.txt", "w") as file_out:
for line in file_in:
key = line.split("\t", 1)[0]
keys[key] += 1
if keys[key] < 3:
file_out.write(line)