Объединение 2 файлов и их сравнение [закрыто]

У меня есть два файла, где я хочу использовать что-то вроде левого соединения, которое используется в SQL.

File1:

column1  column2  column3  column4
Ab       Cd       100      Us
Ef       Gh       200      Us

File2:

column1  column2  column3  column4
Ab       Cd       150      Us

Я хочу, чтобы мой результат выглядел как показано ниже. Мне нужны 3 столбца из первого файла и соответствующее совпадающее значение из второго файла.

column1  column2  column3  column4 
Ab       Cd       100      150
Ef       Gh       200          

Можно ли также получить разность результатов в виде column5?

-2
задан 8 February 2017 в 12:47

2 ответа

Используя join:

join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 file2

Если Вам нужен заголовок для создания отчетов column4 в четвертом поле:

join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 <(awk 'NR == 1 {$3 = "column4"} 1' file2)
join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 <(
    awk '
        NR == 1 {
            $3 = "column4"
        }
        1
    ' file2
)

Это принятие обоих file1 и file2 отсортированы на поле № 1 как в примере.

  • --header: рассматривает первую строку в каждом файле как полевые заголовки, печатая их, не пытаясь соединить их
  • -j1: соединения на поле № 1 file1 и на поле № 1 file2
  • -a1: также печатает unpairable строки из файла file1
  • -o 1.1,1.2,1.3,2.3: поле № 1 печати, № 2 и № 3 file1 сопровождаемый полем № 3 file2
% cat file1
column1  column2  column3  column4
Ab       Cd       100      Us
Ef       Gh       200      Us
% cat file2
column1  column2  column3  column4
Ab       Cd       150      Us
% join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 file2 
column1 column2 column3 column3
Ab Cd 100 150
Ef Gh 200 
% join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 <(awk 'NR == 1 {$3 = "column4"} 1' file2)
column1 column2 column3 column4
Ab Cd 100 150
Ef Gh 200
0
ответ дан 8 February 2017 в 22:47
  • 1
    Спасибо wery очень. Это - мало секретной функции. Мой wisch является одним маленьким значком для этого. – PetaT 13 August 2017 в 01:12

Строго, я должен согласиться, что вопрос находится на краю чисто программного.

В то же время: также соблазняя и бросая вызов, как промежуток, для не ответа, и мы ответили на вопросы как это прежде.

Сценарий

#!/usr/bin/env python3import sys
import sys

files = [[l.split() for l in open(f).readlines()] for f in [sys.argv[1], sys.argv[2]]]
for item in files[0]:
    match = [line for line in files[1] if item[:2] == line[:2]]
    if match:
        try:
            calc = abs(int(int(item[2]) - int(match[0][2])))
            print(("\t").join(item[:3])+"\t"+match[0][2]+"\t", calc)
        except TypeError:
            pass

Как использовать

  • Скопируйте сценарий в пустой файл, сохраните его как analyze.py
  • Выполните его с этими двумя файлами как аргументы:

    python3 /path/to/analyze.py <file1> <file2>
    

От примеров от Вашего вопроса:

$ python3 '/home/jacob/Bureaublad/pscript_1.py' '/home/jacob/Bureaublad/map/f2' '/home/jacob/Bureaublad/map/f1' 
Ab  Cd  150 100  50

Объяснение

Сценарий:

  • ищет строки в двух файлах который первое соответствие на два столбца:

    for item in files[0]:
        match = [line for line in files[1] if item[:2] == line[:2]]
    
  • из согласующих отрезков длинной линии первые два (соответствие) столбцы печатаются, вместе с обеими версиями третьего столбца.

    if match:
        try:
            calc = abs(int(int(item[2]) - int(match[0][2])))
            print(("\t").join(item[:3])+"\t"+match[0][2]+"\t", calc)
        except TypeError:
            pass
    
  • (Абсолютное) различие двух последних столбцов вычисляется (и печатается наконец) в строке:

    calc = abs(int(int(item[2]) - int(match[0][2])))
    

Сценарий принимает:

  • все числа являются целыми числами
  • Вы не хотите распечатывать строки, которые не имеют соответствия первым двум столбцам
  • Каждая из строк только имеет одно возможное соответствие в другом файле
0
ответ дан 8 February 2017 в 22:47

Другие вопросы по тегам:

Похожие вопросы: