Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.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
Python 使用Perl计算管道分隔文本文件的每列中的唯一值_Python_Perl_Unix_Solaris 10 - Fatal编程技术网

Python 使用Perl计算管道分隔文本文件的每列中的唯一值

Python 使用Perl计算管道分隔文本文件的每列中的唯一值,python,perl,unix,solaris-10,Python,Perl,Unix,Solaris 10,我的Solaris服务器主目录中有两个示例管道分隔文件,如下所示: exchnage|ticker|sedol|cusip london |3 |2 |3 newyork |3 |2 |2 file1.txt: ticker|sedol|cusip|exchnage ibm |ibm_1|ib |london hcl | |hcl_02|london hp |hp_01|hpm |newyork

我的Solaris服务器主目录中有两个示例管道分隔文件,如下所示:

exchnage|ticker|sedol|cusip  
london  |3     |2    |3  
newyork |3     |2    |2
file1.txt:

ticker|sedol|cusip|exchnage  
ibm   |ibm_1|ib   |london    
hcl   |     |hcl_02|london    
hp    |hp_01|hpm  |newyork
      |lkp   |lk_2 |newyork
file2.txt:

exchnage|ticker|sedol|cusip  
london  |goo   |goo_1|gm  
london  |hcl   |     |hcl_02  
newyork |hp    |hp_01|hpm  
newyork |tyl   |     |ty_2
我需要一个结果文件,在该文件中,我们将按exchange对ticker、sedol、cusip的唯一计数进行分组:

预期结果文件如下:

exchnage|ticker|sedol|cusip  
london  |3     |2    |3  
newyork |3     |2    |2

我知道使用SQL很容易,但不幸的是数据库不能参与其中。每个文件大小可能高达300-400 MB。我们最好使用Perl,或者如果有困难,那么使用Python。主要环境是Solaris,但我们也可以在Unix服务器上尝试。现在需要添加的是,“exchange”列的位置可以在两个文件中的任何位置进行更改。

我认为,首先需要从文件中创建一个字典列表,如: {'exchnage':'london','ticker':'ibm','sedol':'ibm_1','cusip':'ib'}。然后,您需要一个for-each语句将所有值添加到列表中,但仅当值不是None时,列表中不存在空值(&value)。然后您就得到了列表中所有唯一的值,您需要对它们进行计数。
您需要对文件中的所有列执行此操作。
之后,您需要将其写入一个文件中

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %unique_ticker_count;
my %unique_sedol_count;
my %unique_cusip_count;

my @headers = split( '|', <DATA> );
print @headers;

while ( my $line = <DATA> ) {
    my ( $exchange, $ticker, $sedol, $cusip ) = split( /\|/, $line );
    if ( $ticker =~ m/\w/ ) { $unique_ticker_count{$exchange}{$ticker}++; }
    if ( $sedol =~ m/\w/ )  { $unique_sedol_count{$exchange}{$sedol}++; }
    if ( $cusip =~ m/\w/ )  { $unique_cusip_count{$exchange}{$cusip}++; }
}

print Dumper \%unique_ticker_count;

foreach my $exchange ( keys %unique_ticker_count ) {
    print join( "|",
        $exchange,
        scalar keys %{ $unique_ticker_count{$exchange} } || 0,
        scalar keys %{ $unique_sedol_count{$exchange} }  || 0,
        scalar keys %{ $unique_cusip_count{$exchange} }  || 0,
        ),
        "\n";
}

__DATA__
exchnage|ticker|sedol|cusip  
london  |ibm   |ibm_1|ib  
london  |hcl   |     |hcl_02  
newyork |hp    |hp_01|hpm  
newyork |lkp   |lk_2 |
london  |goo   |goo_1|gm  
london  |hcl   |     |hcl_02  
newyork |hp    |hp_01|hpm  
newyork |tyl   |     |ty_2

我将把文件的打开和处理交给您处理——这只是说明您可以采取的方法

不是最优雅的,而是我为您的新需求打造的最快的:

import glob
import os
import sys

path = "/tmp"
file_mask = "file*.txt"
results = {}

for file in glob.glob(os.path.join(path, file_mask)):
    column_names = {}
    exchange_col = None
    with open(file, "r") as f:
        for line_num, line in enumerate(f.xreadlines()):
            # process header
            if not line_num:
                line_parsed = line.strip().split("|")
                for column_num, column in enumerate(line_parsed):
                    if column.strip() == "exchnage":
                        exchange_col = column_num
                    else:
                        column_names[column_num] = column.strip()
                if exchange_col is None:
                    print "Can't find exchnage field"
                    sys.exit(1)
                continue
            line_parsed = line.strip().split("|")
            if len(line_parsed) != len(column_names) + 1:
                continue
            # prepare empty structure for excahnge, if not added yet
            if not line_parsed[exchange_col].strip() in results:
                results[line_parsed[exchange_col].strip()] = {column_name:set() for column_name in column_names.values()}
            # add uniq items to exchange
            for column_num, column in enumerate(line_parsed):
                column_val = column.strip()
                # add only non empty values
                if column_val and column_num != exchange_col:  
                    results[line_parsed[exchange_col].strip()][column_names[column_num]].add(column_val)

column_names = column_names.values()
print "exchnage|" + "|".join("%8s" %c for c in column_names)
for exchange, values in results.iteritems():
    print "%8s|" % exchange + "|".join("%8s" % str(len(values[column])) for column in column_names)
程序输出(使用不同列顺序的新文件作为输入):


我更喜欢R编程,而很少使用shell…Perl对我来说是一个全新的世界。您能发布一些代码和我们需要使用的Perl包吗?如果你觉得它很大,你可以在purnendumaity@rediffmail.com. “我真的需要这个。”purnendumaity当你问这个问题时,你写了“python”。我看得出来,你把它拿走了。我不知道,如何用perl解决这个问题。这是问题的逻辑,它可以在大多数语言中实现。我没有删除Python…根据上面的命令,Perl是首要任务,但Python解决方案也可以…我可以看到Python标记仍然存在于我的问题中。事实上,在那个特定的系统中,已经有很多东西是用Perl实现的。希望你能理解这些数据,你把假设作为一个单独的文件吗?我有两个文件。。那你是建议合并它们吗?一个文件可能比另一个文件有更多的列,然后将合并工作。。。我只知道检查/计算
数据的列是perl中内联数据的一种方式,这使得演示和发布代码更容易。您可以非常轻松地
打开(my$input,“@Sobrique..根据新的场景,我必须按列位置而不是name@purnendumaity,请注意,它与示例中的文件结构相匹配,并操作列号,而不是名称。因此,如果文件中的列数或列顺序不同,则可能无法使用。@Dieselist..u r正确。现在“exchange”列位于第30列中,因此我应该按如下方式修改它:#为excahnge准备空结构,如果尚未添加,如果未在结果中分析行[0]:results[line\u parsed[0]=[set(),用于xrange中的I(len(行[30:]))]#添加uniq项以交换列_num,enumerate中的列(行_parsed[30:]):@purnendumaity,能否提供新格式?是否为持久性(列号是否可以硬编码)?我们是按列号还是按名称进行操作?u非常有用…我们将按列号进行操作,如果我们使用pandas,然后使用直SQL根,会怎么样…可能,但随后会涉及额外的包安装等事情…我认为他们不会agree@purnendumaity,我已经用新代码更新了我的答案,以满足您的新要求现在它会自动计算出文件中的列顺序。
$ python parser.py
exchnage|  ticker|   sedol|   cusip
 newyork|       2|       2|       3
  london|       3|       2|       3