일부 공유 열을 사용하여 CSV에 가입

일부 공유 열을 사용하여 CSV에 가입

9GB 정도의 대용량 파일 두 개가 있습니다. CSV 파일 1에는 열이 있고 A, B, C, D, ECSV 파일 2에는 열이 있습니다 B, C, F, G. 원하는 출력은 입니다 A, B, C, D, E, F, G. 내가 찾을 수 있는 것은 유사한 열을 결합하고 동일한 열과 연결하는 것입니다. 그러나 여기서 일부는 일치하고 일부는 일치하지 않습니다. 샘플 출력은 다음과 같습니다.

A   B   C   D   E   F   G

1   2   3   4   5   6   7

NaN 1   2   NaN 1   2   1

따라서 열에 대한 값이 없으면 존재하지 않는 것과 같으며 값만 갖기를 원합니다 NaN. 문제를 충분히 설명했기를 바랍니다. 감사해요!

편집: 일반적으로 이렇게 하겠지만, Python이렇게 큰 파일로 인해 청크를 반복하고 마지막에 연결하는 것이 더 짜증납니다. bash내가 모르는 더 직접적인 사용 방법이 있는 것 같습니다 . 감사해요!

답변1


(a) 모든 필드는 엄격하게 탭으로 구분됩니다. (
b) 두 파일(B 및 C)의 공통 열은 동일한 값을 갖습니다.

$ join --nocheck-order -eNaN -13 -22 -t$'\t' -o 1.1 1.2 1.3 1.4 1.5 2.3 2.4 b.txt c.txt
A   B   C   D   E   F   G
1   2   3   4   5   6   7
NaN 1   2   NaN 1   2   1

파일 샘플:

$ cat b.txt
A   B   C   D   E
1   2   3   4   5
    1   2       1
$ cat c.txt
B   C   F   G
2   3   6   7
1   2   2   1

연결 옵션:
-13 -22: 파일 1 열 3(C) = 파일 2 열 2(C)를 기준으로 조인
-t$'\t': 입력 및 출력을 위한 탭 구분 기호
-o: 출력 형식. 1.1은 파일 1, 열 1 등을 의미합니다.
-e : 빈 값을 NaN으로 채웁니다.
자세한 내용은 man joinEven Better를 참조하세요.info join

AWK를 사용하는 대체 솔루션
추신: awk에 대해 인내심을 가지시기 바랍니다. 저는 awk를 처음 배우는 사람입니다.

$ awk -F"\t" '{a[1]="";{for (i=1;i<=NF;i++) if (i==6 ||i==7) continue;else \
if ($i!="") a[1]=a[1]FS$i;else a[1]=a[1]FS"NaN";print a[1]}}' <(paste b.txt c.txt)

쉼표로 구분된 입력 필드 업데이트
귀하의 의견에서 제안한 것처럼 csv 파일은 쉼표로 구분되므로 이 솔루션은 입력 필드를 쉼표로 구분하고 탭을 사용하여 결과를 더 읽기 쉽게 출력합니다.

awk 'BEGIN {FS=",";OFS="\t"}{a[1]="";{for (i=1;i<=NF;i++) if (i==6 ||i==7) continue;else \
if ($i!="") a[1]=a[1]OFS$i;else a[1]=a[1]OFS"NaN";print a[1]}}' <(paste b.txt c.txt)

출력을 쉼표로 인쇄해야 하는 경우 시작 부분을 다음으로 바꾸십시오.{FS=OFS=","}

공통 열/다른 값을 처리하려는 방법은 아직 명확하지 않습니다.

부품을 제거하여 if (i==6 ||i==7) continue;else결과가 필요에 맞는지 확인할 수 있습니다. 이 조건부 검사는 지금까지 파일 2의 두 열이 파일 1의 열과 동일하게 처리되었기 때문에 실제로 필드 6(파일 2의 열 B)과 필드 7(파일 2의 열 C)을 건너뜁니다.

조인 솔루션의 경우: 쉼표로 구분된 필드를 읽으려면 다음 으로
바꾸세요 .-t$'\t'-t','

공통 열의 경우 다음 출력 형식을 사용할 수 있습니다.

join --nocheck-order -eNaN -13 -22 -t',' -o 1.1 1.2 2.1 1.3 2.2 1.4 1.5 2.3 2.4 b.txt c.txt

관련 정보