Unindo dois arquivos de texto com várias chaves

2

Eu tenho dois conjuntos de dados. e quero uni-los por dois valores-chave (storm_ID, Cell_ID).

O primeiro conjunto de dados se parece com:

Storm_ID,Cell_ID,Wind_speed 
2,10236258,27 
2,10236300,58 
2,10236301,25 
3,10240400,51

O segundo conjunto de dados se parece com:

Storm_ID,Cell_ID,Storm_surge 
2,10236299,0.27 
2,10236300,0.27 
2,10236301,0.35 
2,10240400,0.35 
2,10240401,0.81 
4,10240402,0.11

Agora eu quero uma saída que se pareça com isso:

Storm_ID,Cell_ID,Wind_speed,Storm_surge 
2,10236258,27,0 
2,10236299,0,0.27 
2,10236300,58,0.27 
2,10236301,25,0.35 
2,10240400,0,0.35 
2,10240401,0,0.81 
3,10240400,51,0 
4,10240402,0,0.11

Eu tentei juntar o comando no Linux para executar essa tarefa e falhei mal. O comando Join ignorou as linhas que não correspondiam no banco de dados. Posso usar o Matlab, mas o tamanho dos dados é superior a 100 GB, o que dificulta muito essa tarefa. Alguém pode me guiar por favor? Posso usar o SQL ou python para concluir esta tarefa.

    
por Sami 30.03.2018 / 03:53

2 respostas

3

Você pode poder fazer isso com join se mesclar os dois primeiros campos em uma única chave, substituindo o separador por vírgula por um caractere que você pode ter certeza de que não aparecerá em seu dados. Observe que, como join exige que os dados sejam classificados no campo de junção, isso só funcionará se isso não alterar a ordem lexical dos dados.

Por exemplo:

$ join -t, -a1 -a2 -e0 -o0,1.2,2.2 <(sed 's/,/;/' file1) <(sed 's/,/;/' file2) | sed 's/;/,/'
Storm_ID,Cell_ID,Wind_speed,Storm_surge
2,10236258,27,0
2,10236299,0,0.27
2,10236300,58,0.27
2,10236301,25,0.35
2,10240400,0,0.35
2,10240401,0,0.81
3,10240400,51,0
4,10240402,0,0.11
    
por steeldriver 30.03.2018 / 15:01
5

Usando o awk e classifique:

awk -F, -v OFS=, '{x = $1 "," $2} FNR == NR {a[x] = $3; b[x] = 0; next} {b[x] = $3} !a[x] {a[x] = 0} END {for (i in a) print i, a[i], b[i]}' f1 f2 | sort -n
  • -F, -v OFS=, - define a entrada e a saída como separadas por ,
  • {x = $1 "," $2} salve os dois primeiros campos separados por , , pois a combinação é o índice comum.
  • FNR == NR {a[x] = $3; b[x] = 0; next} - FNR é o número de registros por arquivo e NR é o número total de registros nos arquivos. Estes são iguais para o primeiro arquivo, então este bloco é executado apenas para o primeiro arquivo. Aqui, salve a terceira coluna do primeiro arquivo na matriz a e inicialize a entrada correspondente em b para 0. E então pulo para o próximo registro.
  • {b[x] = $3} !a[x] {a[x] = 0} - esses dois são executados para o segundo arquivo, salvando a terceira coluna em b e, se não houver uma entrada correspondente em a , defina-o como 0.
  • END {for (i in a) print i, a[i], b[i]} , no final de ambos os arquivos, imprima todos os registros obtidos até o momento

Como o loop over arrays no awk fornece uma ordem aleatória, precisamos classificar a saída no final com sort -n :

$ awk -F, -v OFS=, '{x = $1 "," $2} FNR == NR {a[x] = $3; b[x] = 0; next} {b[x] = $3} !a[x] {a[x] = 0} END {for (i in a) print i, a[i], b[i]}' f1 f2 | sort -n
Storm_ID,Cell_ID,Wind_speed,Storm_surge
2,10236258,27,0
2,10236299,0,0.27
2,10236300,58,0.27
2,10236301,25,0.35
2,10240400,0,0.35
2,10240401,0,0.81
3,10240400,51,0
4,10240402,0,0.11
    
por muru 30.03.2018 / 04:31