Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Perl、Python或bash更改列中的值运行_Python_Perl_Bash - Fatal编程技术网

如何使用Perl、Python或bash更改列中的值运行

如何使用Perl、Python或bash更改列中的值运行,python,perl,bash,Python,Perl,Bash,我希望遍历大量以制表符分隔的文件,并按以下方式更改单个列: 原创的 Col1 Col2 .... afawer 1 asdgf 1 aser 1 qwerq 10 a3awer 10 1sdgf 11 a55er 11 2wu9 12 asxwer 12 a2dgf 13 a1er 13 qperq 13 ... 期望的替代品 Col1 Col2 .... afawer 1 asdgf 1 aser 1 qwe

我希望遍历大量以制表符分隔的文件,并按以下方式更改单个列:

原创的

Col1    Col2    ....
afawer  1
asdgf   1
aser    1
qwerq   10
a3awer  10
1sdgf   11
a55er   11
2wu9    12
asxwer  12
a2dgf   13
a1er    13
qperq   13
...
期望的替代品

Col1    Col2    ....
afawer  1
asdgf   1
aser    1
qwerq   2
a3awer  2
1sdgf   3
a55er   3
2wu9    4
asxwer  4
a2dgf   5
a1er    5
qperq   5
...
请注意,Col2中的运行长度对于每个文件都会有很大的不同,因此不能硬编码长度。基本上,我要替换的模式是:

aaabbbbcccddd

其中a,b,c和d可以是任何整数。所需的替换是:

111222233334444

以此类推(即整数的自然顺序)

我希望使用Python或Perl来实现这一点,或者如果可能的话,只使用bash命令,如
sed

使用Python,可以对第二列上的行进行分组,并使用以下命令提供的计数器:


这将使用相同的数据写入一个新的CSV文件,但第二列被计数器(从1开始)替换,该计数器在第2列中的原始值每次更改时都会递增。

使用
awk
您可以说:

awk 'NR>1{if ($2 == prev) { $2 = a; } else { prev=$2; a=a+1; $2=a; }}1' OFS='\t' filename
对于您的输入,它将产生以下输出:

Col1    Col2
afawer  1
asdgf   1
aser    1
qwerq   2
a3awer  2
1sdgf   3
a55er   3
2wu9    4
asxwer  4
a2dgf   5
a1er    5
qperq   5

要完成您要求的三种语言,请看以下Perl版本。 如果Col2值稍后重复,也可以使用。 编辑:我使用了一个空格作为delimeter,替换为一个选项卡

use strict;
use warnings;

open (INFILE, "<", "infile.csv");
my @lines = <INFILE>;
close INFILE;

open (OUTFILE, ">", "outfile.csv");
my %hash = ("Col2", "Col2"); #  To handle the Header
my $counter=0;

foreach my $currentLine (@lines)
{
    chomp $currentLine;
    my @fields = split (/\W+/, $currentLine);
    if (!exists $hash{$fields[1]})  # Have I not seen the Col2 value before?
    {
        $counter++;                 # If not, determine what to replace the value with. 
        $hash{$fields[1]} = $counter;
    }
    $fields[1] = $hash{$fields[1]}; # Replace with known replacement.

    print OUTFILE $fields[0],"\t",$fields[1],"\n";
}
使用严格;
使用警告;
打开(infle,“,”outfile.csv“);
我的%hash=(“Col2”,“Col2”)#处理标题
我的$counter=0;
foreach my$currentLine(@lines)
{
chomp$currentLine;
my@fields=拆分(/\W+/,$currentLine);
如果(!exists$hash{$fields[1]})#我以前没有看到Col2值吗?
{
$counter++#如果不是,请确定用什么替换该值。
$hash{$fields[1]}=$counter;
}
$fields[1]=$hash{$fields[1]};#替换为已知替换。
打印输出文件$fields[0],“\t”,$fields[1],“\n”;
}

这是一个非常简单的Perl解决方案。它只跟踪第二列的前一个值,如果它发生更改,则会碰撞
$n
的值

程序希望输入文件的路径作为命令行上的参数,并将修改后的数据发送到STDOUT

use strict;
use warnings;

print scalar <>; # Copy header line

my ($prev, $n) = (0, 0);
while (<>) {
  chomp;
  my @fields = split /\t/;
  ($prev, $fields[1]) = ($fields[1], $fields[1] == $prev ? $n : ++$n);
  print join("\t", @fields), "\n";
}
使用严格;
使用警告;
打印标量;#复制标题行
我的($prev,$n)=(0,0);
而(){
咀嚼;
我的@fields=split/\t/;
($prev,$fields[1])=($fields[1],$fields[1]==$prev?$n:++$n);
打印联接(“\t”,@字段),“\n”;
}

您能详细解释一下这个模式吗?所需的替代品是数字1、2、3……的自然顺序的可变长度运行,。。。等。要替换的模式是编号的运行,可能没有特定的顺序(尽管每次运行时的编号应该是唯一的),因此第二个要替换的运行对象“10”不应再次弹出。请显示您尝试过的内容,并描述您遇到的问题,然后我们可以帮助您。堆栈溢出是一个在你陷入自己的编程工作时获得帮助的地方,而不是一个免费编程劳动的来源。这听起来应该是可行的。我会试试看。但是,(很抱歉缺乏python知识)如何对制表符分隔的文件而不是csv执行此操作?@oisyuta:这是针对制表符分隔的文件。
csv
模块在这里处理通用的分隔文件,读写器都配置为使用
\t
(制表符)作为分隔符。这甚至不会编译。而且,它只生成两列输出,如果数据中有标点符号,就会失控,并且需要将标题标签硬编码到程序中。@Borodin:嗯,关于编译的内容,你确实是对的。对此我很抱歉,我在另一台机器上测试了它,并没有费心把它发送给post,只是输入了它。关于你的其他评论:我没有费心把所有的可能性都包括进去,真丢脸。我没想到会有人冲我来要求回答。但除了缺少“”和一个l而不是l之外,它还满足Op的要求。而且,是的,我完全希望Op能根据他们的实际需要调整总体思路,我不是他们的代码猴子。这不是一个很好的答案,我给你这个答案,但不到零?我认为这不够好,足以保证投反对票。如果其他人不同意我的意见,那么你的票数将会增加。@Borodin:在0和-1之间有一大步。我理解,这不是为了你(我看到你的答案非常详细,你可能永远都不会接近),但低于0的向下投票意味着我一开始就不应该回答。我的回答不仅没有真正帮助Op,甚至伤害了他们。这就是为什么否决票困扰着我。但不管怎样,我不能从众议员那个里买任何东西。我刚才看到,你们是我迄今为止看到的第一个投反对票多于投赞成票的人(这是多么大的差距),所以我怀疑这是否真的与你们有关。继续回答这个好问题。你必须明白我的投票不应该取决于它留给你的总数?我必须记下你的名字,因为你的代码并不能解决这个问题:数据中的省略号清楚地表明实际上有很多列数据,你正在丢弃除前两列以外的所有列。我对自己的投票记录并不感到自豪,我清楚地知道,我投票——特别是问题——太少了。我的观点倾向于过于黑白,所以要么答案是对的,要么不是,所以一无所获,要么投反对票。我欢迎你的评论,提醒大家在每一种情况下都要考虑投票。
use strict;
use warnings;

print scalar <>; # Copy header line

my ($prev, $n) = (0, 0);
while (<>) {
  chomp;
  my @fields = split /\t/;
  ($prev, $fields[1]) = ($fields[1], $fields[1] == $prev ? $n : ++$n);
  print join("\t", @fields), "\n";
}