정렬된 파일을 두 열로 병합

정렬된 파일을 두 열로 병합

미리 정렬된 탭으로 구분된 파일을 병합하고 싶습니다.

  • 문서 bygroup.0:
    ancient-american    mercury 1   164
    ancient-american    mh25    2   8717664
    ancient-neolith tk11    262 40074321970
    ancientdna  jk21    6936    17069206689
    ancientdna  rm20    11267   372606702813
    ancientgen  ab34    1573    27800468142
    ancientgen  dg11    3516    45081427920
    ancientgen  fa8 7179    462396221983
    ancientgen  mp15    41  10248223517
    ancientgen  mp18    254 1049351143
    ancientgen  rm20    15100   1565340401
    ancientgen  tc9 1695    89861489631
    
  • 문서 bygroup.2:
    ancient-american    mercury 1   160
    ancient-american    mh25    2   10362712888
    ancient-neolith tk11    264 43842268110
    ancientdna  jk21    6919    16379509855
    ancientdna  rm20    11268   324906365415
    ancientgen  ab34    1577    33947364202
    ancientgen  dg11    3518    48092138390
    ancientgen  fa8 7174    472364587220
    ancientgen  mp15    39  32487920045
    ancientgen  mp18    254 1058177852
    ancientgen  rm20    15104   998615135
    ancientgen  tc9 1692    94858351562
    

두 파일 모두 동일한 행 수를 가지며 열 1과 2를 기준으로 동일한 순서로 되어 있으며 해당 열의 항목이 동일하다는 것을 알 수 있습니다.

이제 처음 두 열의 값이 동일한 모든 행이 순서대로 출력되도록 병합하고 싶습니다.

sort -m나는 이것이 나에게 필요한 것이라고 생각했지만 ,

$ sort -m bygroup.*
ancient-american    mercury 1   160
ancient-american    mercury 1   164
ancient-american    mh25    2   10362712888
ancient-american    mh25    2   8717664
ancient-neolith tk11    262 40074321970
ancientdna  jk21    6936    17069206689
ancientdna  rm20    11267   372606702813
ancientgen  ab34    1573    27800468142
ancientgen  dg11    3516    45081427920
ancientgen  fa8 7179    462396221983
ancientgen  mp15    41  10248223517
ancientgen  mp18    254 1049351143
ancientgen  rm20    15100   1565340401
ancientgen  tc9 1695    89861489631
ancient-neolith tk11    264 43842268110
ancientdna  jk21    6919    16379509855
ancientdna  rm20    11268   324906365415
ancientgen  ab34    1577    33947364202
ancientgen  dg11    3518    48092138390
ancientgen  fa8 7174    472364587220
ancientgen  mp15    39  32487920045
ancientgen  mp18    254 1058177852
ancientgen  rm20    15104   998615135
ancientgen  tc9 1692    94858351562

(내가 추가한 다른 옵션에서도 동일한 결과를 얻었습니다. sort -k 1,2 -ifm...)

그것은 고대 미국인에 대한 나의 기대에 부합하지만 다른 사람들에게는 그렇지 않습니다. 무슨 일이 일어나고 있으며 전체 정렬( sort여기서는 필요 없이 작동함 -m)에 의존하지 않고 이 작업을 수행할 수 있는 또 다른 빠르고 효율적인 방법이 있습니까?

답변1

TXR Lisp 솔루션:

$ txr merge.tl 
ancient-american    mercury 1   164
ancient-american    mercury 1   160
ancient-american    mh25    2   8717664
ancient-american    mh25    2   10362712888
ancient-neolith tk11    262 40074321970
ancient-neolith tk11    264 43842268110
ancientdna  jk21    6936    17069206689
ancientdna  jk21    6919    16379509855
ancientdna  rm20    11267   372606702813
ancientdna  rm20    11268   324906365415
ancientgen  ab34    1573    27800468142
ancientgen  ab34    1577    33947364202
ancientgen  dg11    3516    45081427920
ancientgen  dg11    3518    48092138390
ancientgen  fa8 7179    462396221983
ancientgen  fa8 7174    472364587220
ancientgen  mp15    41  10248223517
ancientgen  mp15    39  32487920045
ancientgen  mp18    254 1049351143
ancientgen  mp18    254 1058177852
ancientgen  rm20    15100   1565340401
ancientgen  rm20    15104   998615135
ancientgen  tc9 1695    89861489631
ancientgen  tc9 1692    94858351562

암호:

(defstruct record ()
  key
  line
  (:method equal (me) me.key))

(defun read-recs (file)
  (build
    (awk (:set fs "\t")
         (:inputs file)
         (t (add (new record
                      key [f 0..2]
                      line rec))))))

(mapdo [chain .line put-line] (merge (read-recs "bygroup.0") (read-recs "bygroup.1")))

파일의 각 레코드에 대한 정보를 보유하기 위해 정렬 키인 recorda 와 원시 축어 행인 a를 포함하는 구조 유형을 정의합니다. 슬롯 은 두 개의 문자열 목록이 됩니다.keylinekey

record유형에는 equal다음을 구현하는 메소드 가 있습니다.동등한 대체. 즉, record함수가 전달되거나 equal객체 less가 비교될 때마다 greater객체 대신 해당 메서드의 값이 사용됩니다. 예를 들어, 비교 함수를 지정하지 않고 sort구조체 목록에 액세스한다면 record해당 구조체는 키를 기준으로 정렬됩니다.

이 함수는 read-recs표준 awkAwk에서 필드 구분 기호를 "\t" (tab). For each record, thet condition (unconditional truth) dispatches an action which creates a record object. Thekey is a sublist of thef (field) list, consisting of the first two fields. Theline is therec $0`로 지정합니다.: the whole record.is like

build매크로는 암시적, 절차적 목록 작성에 사용됩니다. 예를 들어 (build (add 1) (add 2))목록이 반환됩니다 (1 2). 종료 시 반환되는 build암시적 숨겨진 목록에 호출이 추가되는 범위를 만듭니다 .addbuild

read-recs등치 치환을 사용하면 필요한 키를 올바르게 입력하는 유형이 있으므로 두 파일을 모두 읽고 정렬된 목록을 얻기 위해 record함수에 전달하기만 하면 됩니다 .merge

record이 목록의 개체는 두 가지 함수의 연결을 통해 매핑됩니다. [chain .line put-line]이 함수는 개체의 슬롯을 .line검색 한 다음 이를 표준 출력에 덤프하고 그 뒤에 개행 문자가 옵니다.lineput-line


read-recsand를 사용하지 않고 build함수를 구현하는 방법은 다음 awk과 같습니다.

(defun read-recs (file)
  (collect-each ((line (file-get-lines file)))
    (let ((fields (spl #\tab line)))
      (new record key [fields 0..2]
                  line line))))

답변2

R 프로그래밍 언어 사용

하나 이상의 공백 문자를 단일 탭 문자로 대체하여 텍스트 파일을 저장합니다. 두 개의 데이터 파일을 R로 읽습니다.

> group0 <- read.delim("/Users/admin/bygroup.0", header=FALSE)
> group2 <- read.delim("/Users/admin/bygroup.2", header=FALSE)
> head(group0)
                V1      V2    V3           V4
1 ancient-american mercury     1          164
2 ancient-american    mh25     2      8717664
3  ancient-neolith    tk11   262  40074321970
4       ancientdna    jk21  6936  17069206689
5       ancientdna    rm20 11267 372606702813
6       ancientgen    ab34  1573  27800468142
> head(group2)
                V1      V2    V3           V4
1 ancient-american mercury     1          160
2 ancient-american    mh25     2  10362712888
3  ancient-neolith    tk11   264  43842268110
4       ancientdna    jk21  6919  16379509855
5       ancientdna    rm20 11268 324906365415
6       ancientgen    ab34  1577  33947364202

데이터 파일을 병합하려면 R의 merge()기능을 사용하십시오.

> merge(group0, group2, by = c("V1","V2"))
                 V1      V2  V3.x         V4.x  V3.y         V4.y
1  ancient-american mercury     1          164     1          160
2  ancient-american    mh25     2      8717664     2  10362712888
3   ancient-neolith    tk11   262  40074321970   264  43842268110
4        ancientdna    jk21  6936  17069206689  6919  16379509855
5        ancientdna    rm20 11267 372606702813 11268 324906365415
6        ancientgen    ab34  1573  27800468142  1577  33947364202
7        ancientgen    dg11  3516  45081427920  3518  48092138390
8        ancientgen     fa8  7179 462396221983  7174 472364587220
9        ancientgen    mp15    41  10248223517    39  32487920045
10       ancientgen    mp18   254   1049351143   254   1058177852
11       ancientgen    rm20 15100   1565340401 15104    998615135
12       ancientgen     tc9  1695  89861489631  1692  94858351562

write.delim()또는 함수를 사용하여 데이터를 다시 쓸 수 있습니다 write.csv(). 도움말을 보려면 프롬프트에 , 또는 ?getwd()와 같은 물음표 앞에 명령을 입력하세요 ?setwd().?read.delim()?merge()

[참고: R 설치 기간에 따라 stringsAsFactors=FALSE모든 함수 호출 read.delim()에 이 인수를 포함 해야 할 수도 있습니다.]

https://www.r-project.org/
https://cran.r-project.org/index.html

관련 정보