contando ocorrências de padrão de um arquivo de entrada para corresponder a um arquivo enorme

2

Eu tenho uma lista de faculdades em um arquivo de texto e, em um arquivo separado, tenho uma lista de publicações com afiliação. Quero escrever um roteiro, verificar quantas vezes uma publicação é repetida e contar o número de vezes que as universidades colaboraram. Meus dados estão abaixo; "p1" é o título do artigo, "Afiliação" são as faculdades envolvidas para publicá-lo

Exemplo: -

Dados

UID, afiliação

p1    "ADPRI, S"
p1    "ADPRI, S"
p2    "ADPRI, S"
p2    "AAC&S, H"
p3    "AAC&S, H"
p3    "HU, USA" 
p3    "Penn, USA"
p4    "AAC&S, H"  
p5    "AAC&S, H"  
p6    "AAC&S, H"  
p7    "AAC&S, H"  
p8    "AU, A"  
p9    "AECI, A"  
p10   "AECI, A" 
p10   "AECI, A" 

Nos dados acima, o artigo "p2" está vinculado a "ADPRI, S" e "AAC & S, H".
Da mesma forma "p3" está ligado às faculdades "AAC & S, H", "HU, EUA", "Penn, EUA".
Portanto, meu script deve fornecer um arquivo em que a contagem do número de colaboração seja dada entre duas faculdades. Para os dados acima, será

Saída desejada:

 College_A       College_B       Collaborated
  ADPRI, S       AAC&S, H            2
  HU, USA        Penn, USA           1
  ....
  ....
 so on for all the colleges,

** Eu usei o comando sort e uniq na "coluna 2", para obter o número de faculdades, que é uma lista de 797 faculdades e meu banco de dados tem mais de 20000 artigos publicados por essas faculdades. Meus dados também possuem muitos espaços em branco e caracteres especiais. **

PS: - Os dados são separados por tabulações, tenho os mesmos dados em CSV também.

    
por CCC 02.11.2017 / 17:32

2 respostas

1

gawk solution.

Uso: ./program.awk input.txt

Além disso, você pode fazer: ./program.awk input.txt | column -t -s $'\t' para a exibição bonita, se o alinhamento for perdido.

#!/usr/bin/awk -f

function pub_to_aff() {
    for(i in pub_arr) {
        for(j in pub_arr) {
            if(i != j)
                aff_arr[i][j]++;    
        }   
    }   
    delete pub_arr;
}

BEGIN {
    OFS = "\t";
    FS = "\t";
}

$1 != prev_uid {
    prev_uid = $1; 
    pub_to_aff();
}
{
    pub_arr[$2] = 1;
}

END {
    pub_to_aff();
    print "College_A", "College_B", "Collaborated";

    for(i in aff_arr) {
        for(j in aff_arr[i]) {
            print i, j, aff_arr[i][j];          
        }   
    }   
}

Entrada - duas linhas foram adicionadas para demonstração - para p3 e p4 .

p1  "ADPRI, S"
p1  "ADPRI, S"
p2  "ADPRI, S"
p2  "AAC&S, H"
p3  "AAC&S, H"
p3  "ADPRI, S"
p3  "HU, USA"
p3  "Penn, USA"
p4  "AAC&S, H"
p4  "ADPRI, S"
p5  "AAC&S, H"
p6  "AAC&S, H"
p7  "AAC&S, H"
p8  "AU, A"
p9  "AECI, A"
p10 "AECI, A"
p10 "AECI, A"

Saída

College_A   College_B   Collaborated
"AAC&S, H"  "HU, USA"   1
"AAC&S, H"  "Penn, USA" 1
"AAC&S, H"  "ADPRI, S"  3
"HU, USA"   "AAC&S, H"  1
"HU, USA"   "Penn, USA" 1
"HU, USA"   "ADPRI, S"  1
"Penn, USA" "AAC&S, H"  1
"Penn, USA" "HU, USA"   1
"Penn, USA" "ADPRI, S"  1
"ADPRI, S"  "AAC&S, H"  3
"ADPRI, S"  "HU, USA"   1
"ADPRI, S"  "Penn, USA" 1

EDIT - teste de dados reais.

Entrada - deixei apenas parte do conteúdo do seu exemplo.txt e alterei algumas linhas para demonstração do funcionamento do script. Observe que, se o arquivo de entrada não contiver universidades colaboradas, o script exibirá apenas uma linha - cabeçalho.

WOS:000355337800046 "ACHARYA NARENDRA DEV COLL, NEW DELHI"
WOS:000355337800046 "ACHARYA NARENDRA DEV COLL, NEW DELHI"
WOS:000355337800046 "ACHARYA PRAFULLA CHANDRA COLL. KOLKATA"
WOS:000328700900001 "ACHARYA PRAFULLA CHANDRA COLL. KOLKATA"
WOS:000338233800012 "ADAMAS INST TECHNOL, KOLKATA"
WOS:000338233800012 "ADARSH MAHAVIDYALAYA DHAMANGAON RAILWAY, AMRAVATI"
WOS:000349637600009 "ADARSH MAHAVIDYALAYA DHAMANGAON RAILWAY, AMRAVATI"
WOS:000314892400031 "ADITYA INST TECHNOL & MANAGEMENT, TEKKALI"

Comando usado: ./program.awk sample.txt | column -t -s $'\t'

Saída

College_A                                            College_B                                            Collaborated
"ADAMAS INST TECHNOL, KOLKATA"                       "ADARSH MAHAVIDYALAYA DHAMANGAON RAILWAY, AMRAVATI"  1
"ACHARYA NARENDRA DEV COLL, NEW DELHI"               "ACHARYA PRAFULLA CHANDRA COLL. KOLKATA"             1
"ACHARYA PRAFULLA CHANDRA COLL. KOLKATA"             "ACHARYA NARENDRA DEV COLL, NEW DELHI"               1
"ADARSH MAHAVIDYALAYA DHAMANGAON RAILWAY, AMRAVATI"  "ADAMAS INST TECHNOL, KOLKATA"                       1
    
por 03.11.2017 / 22:49
2

com o Perl:

#!/usr/bin/env perl

use strict;
use warnings;

use List::MoreUtils qw(uniq);
use Set::Intersection;

my ( %papers, @colleges );

while (<>) {          
    chomp; 
    my ( $paper, $college ) = m/(\S+)\t"(.+)"/g;

    # normalize college names
    $college =~ s/\s\+/ /go;
    $college =~ s/^\s\+//go;
    $college =~ s/\s\+$//go;

    $papers{$college} //= [];
    push @{ $papers{$college} }, $paper;
}

@colleges = sort keys %papers;
for my $college (@colleges) {
    $papers{$college} = [ uniq sort @{ $papers{$college} } ];
}

print qq(College_A\tCollege_B\tCollaborated\n);
for ( my $i = 0 ; $i < @colleges - 1 ; $i++ ) {
    for ( my $j = $i + 1 ; $j < @colleges ; $j++ ) {
        my $collaborations = scalar get_intersection(
            { -preordered => 1 },
            $papers{ $colleges[$i] },
            $papers{ $colleges[$j] }
        );  
        print $colleges[$i], "\t", $colleges[$j], "\t", $collaborations, "\n"
          if ($collaborations);
    }
}

Com o Python:

#!/usr/bin/env python

from __future__ import print_function

import re
import sys
from collections import defaultdict

papers = defaultdict(lambda: set())
for line in sys.stdin:
    paper, college = line.split("\t")
    college = re.sub(r'^"|"$', '', college)
    college = re.sub(r'\s+', ' ', college)
    college = re.sub(r'^\s+|\s+$', '', college)
    papers[college].add(paper)

colleges = sorted(papers.keys())

print("College_A\tCollege_B\tCollaborated")
for i in range(len(colleges) - 1):
    for j in range(i + 1, len(colleges)):
        collaborations = len(papers[colleges[i]].intersection(papers[colleges[j]]))
        if collaborations:
            print("%s\t%s\t%d" % (colleges[i], colleges[j], collaborations))
    
por 02.11.2017 / 19:13