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

2024-06-01 14:21:55 发布

您现在位置:Python中文网/ 问答频道 /正文

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

文件1.txt:

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

文件2.txt:

^{pr2}$

我需要一个结果文件,我们将把ticker、sedol、cusip的唯一计数按exchange分组:

预期结果文件如下:

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

我知道使用SQL很容易,但不幸的是数据库不能涉及。每个文件的大小可能会达到300-400 MB。我们最好是用Perl或者Python来完成。主环境是Solaris,但我们也可以在Unix服务器上尝试。现在需要增加的是“exchange”列的位置可以在两个文件中的任何位置。在


Tags: 文件服务器txtexchangeibmhptickerlondon
3条回答
#!/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

将打印:

^{pr2}$

我将把它留给你来处理文件的打开和处理-这只是说明你可以采取的方法。在

我想,首先你需要从这些文件中创建一个字典列表,比如: {'exchnage':'london','ticker':'ibm','sedol':'ibm'u 1','cusip':'ib'}。而不是需要for each satement将所有值添加到列表中,但仅当值不是“无”时,空值不在列表中。然后你就得到了列表中所有的唯一值,你需要对它们进行计数。
您需要对文件中的所有列执行此操作。
之后,你需要把这个写在一个文件里。在

不是最优雅的,而是我为您的新要求而设计的最快的:

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)

程序输出(作为输入,使用了列顺序不同的新文件):

^{pr2}$

相关问题 更多 >