첫 번째 줄을 기준으로 열을 정렬하는 방법은 무엇입니까?


12

매우 큰 데이터 세트의 열을 정렬해야합니다 (1000 줄 및 700000 열). 예를 들어, 내 열은 무작위로 col1 col4 col3 col2와 같이 정렬되며 정렬해야합니다.

나는 몇 가지 명령을 시도했지만 성공하지 못했습니다.

예:

ID M2 M5 M8 M1 M3 M9 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln

이 예에서 점은 많은 열과 선이 있음을 의미합니다. 다시, 나는 열을 다음과 같이 정렬해야합니다.

ID M1 M2 M3 M4 M5 M6 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln

감사합니다


몇 줄의 데이터 세트로 예제를 추가 할 수 있습니까?
jcbermu

예상 결과에 첫 줄만 정렬되어 있고 다른 값은 동일하게 유지되는 이유는 무엇입니까?
RomanPerekhrest

실제로, 그것은 열을 따라야하며, 예제의 실수였습니다. 죄송합니다
LLVerardo

첫 번째 줄을 기준으로 전체 열을 정렬해야합니다.
LLVerardo 2016 년

2
조옮김, 첫 번째 열을 기준으로 다시 조옮김.
Satō Katsura

답변:


10

GNU datamash와 GNU로 sort:

datamash transpose -t ' ' -H <file_in.csv | sort -V | datamash transpose -t ' ' -H >file_out.csv

이것은 "합리적으로 작은"데이터에 적합합니다. 파일과 함께 작동하거나 작동하지 않을 수 있습니다.

편집 : 전치가없는 아래 솔루션은 덜 리소스 집약적이어야합니다.


1
RS 명령 에 가벼운 대안이 될 수있는 datamash예는 rs -T < file_in.csv | sort | rs -T -C' '( rs데비안 기반 시스템에서 패키지로 사용할 수 있어야합니다)
steeldriver

2
FWIW rs( "데이터 배열 재구성")는 일부 BSD의 기본 시스템에서 사용할 수 있습니다.
Kusalananda

6
perl -pale '
   $. == 1 and
   @I = map  { $_->[1] }
        sort { $a->[0] <=> $b->[0] }
        map  { [ $F[$_] =~ /^M(\d+)$/, $_ ] } 1..$#F;
   $_ = "@F[0, @I]";
' yourlargefile

  1. 첫 번째 줄의 M경우 잘 알려진을 사용하여 처음에 나오는 숫자 다음에 숫자 부분을 사용하여 두 번째 ... 마지막 열로 숫자로 정렬합니다 Schwartzian maneuver. 이렇게하면 인덱스가 재정렬되어 열이 숫자 순으로 정렬됩니다 (M1, M2, M3, ...)
  2. 남아있는 것은이 인덱스를 사용 @I하여 @F요소 를 다시 정렬하는 것 입니다.
  3. 큰 따옴표 형태로 배열을 할당하면 요소 공간이 분리 된 문자열로 배열이 변환됩니다.
  4. -pPerl 옵션은 $_내용 의 자동 인쇄를 가능하게 -l합니다 newline.

6

perl 모듈 사용하기 Sort :: Naturally

입력 데이터

ID M2 M5 M8 M1 M3 M9 M700000
A1 m1,2 m1,5 m1,8 m1,1 m1,3 m1,9 m1,7000000
A2 m2,2 m2,5 m2,8 m2,1 m2,3 m2,9 m2,7000000
A3 m3,2 m3,5 m3,8 m3,1 m3,3 m3,9 m3,7000000
A1000 m1000,2 m1000,5 m1000,8 m1000,1 m1000,3 m1000,9 m1000,7000000
perl -MSort::Naturally -lane '
  if ($. == 1) {
    @indices = (0, map  { $_->[0] }
                   sort { ncmp($a->[1], $b->[1]) }
                   map  { [$_, $F[$_]] }
                   1..$#F
               );
    $, = " ";
  }
  print @F[@indices]
' test.data

산출

ID M1 M2 M3 M5 M8 M9 M700000
A1 m1,1 m1,2 m1,3 m1,5 m1,8 m1,9 m1,7000000
A2 m2,1 m2,2 m2,3 m2,5 m2,8 m2,9 m2,7000000
A3 m3,1 m3,2 m3,3 m3,5 m3,8 m3,9 m3,7000000
A1000 m1000,1 m1000,2 m1000,3 m1000,5 m1000,8 m1000,9 m1000,7000000

가장 우아한 +1은 열 이름에 대해 너무 구체적인 접두사를 가정하지 않으며 하나의 패스 솔루션입니다.
arielf 2016 년

4

당신이있는 경우 rs유틸리티가 설치되어, 당신은이 작업을 수행 할 수 있습니다 :

rs -c' ' -T | {
    stdbuf -i0 sed "1q"
    sort -V
} | rs -C' ' -T

또는 한 줄에 모두 :

rs -c' ' -T | { stdbuf -i0 sed "1q"; sort -V ; } | rs -C' ' -T
  • 첫 번째 rs는 입력 데이터를 바꿉니다 (공백으로 구분 된 필드 포함)
  • 명령 그룹 :
    • sed첫 번째 줄을 읽고 출력 한 다음 종료하여 파이프의 나머지 부분은 그대로 둡니다 rs. 입력 버퍼링을 해제하여 첫 번째 줄 바꿈까지만 읽고 더 이상 읽지 stdbuf않도록해야합니다.sed
    • sort남은 줄
  • 두 번째 rs는 결과 스트림을 원래 형식으로 다시 바꿉니다.

rsMacOS에 기본적으로 설치됩니다. Linux 시스템에서는 설치해야 할 수 있습니다 (예 :

sudo apt install rs

주의 사항 stdbufsorts -V옵션은 GNU에 따라 다르므로 수정되지 않은 MacOS에서는 작동하지 않습니다.


0

GNU가 있다면 다음을 awk시도해보십시오.

NR == 1 {
    for (i = 2; i <= NF; i++) {
        columns[substr($i, 2)] = i;
    }
    count = asorti(columns, sorted, "@ind_num_asc");
    printf("%s", $1);
    for (i = 1; i <= count; i++) {
        printf(" M%s", sorted[i]);
        indx[i] = columns[sorted[i]];
    }
    print "";
    next;
}
{
    printf("%s", $1);
    for (i = 1; i <= count; i++) {
        printf(" %s", $(indx[i]));
    }
    print "";
}

0

파이썬에서 :

from csv import DictReader, DictWriter
with open('in_file.csv') as infile, open('out_file.csv') as outfile:
  reader = DictReader(infile)
  writer = DictReader(outfile, fieldnames=sorted(reader.fieldnames))
  writer.writerows(reader)

0

당신이 이것을 좋은 대답이라고 생각하는지 모르겠지만 ...

왜이 문제를 해결하기 위해 데이터베이스를 사용하지 않습니까? 데이터 세트를 임시 테이블로 가져 와서

SELECT column1, column2, ... column-n FROM my_temp_table

필요에 따라 다른 필터 또는 변환을 사용할 수 있습니다. 그런 다음 필요에 따라 출력을 다시 포맷 할 수 있습니다.

이 모든 작업은 bash 스크립트로 프로그래밍하고 파이프를 사용하여 출력을 연결합니다.

때때로 나는 "pv"명령을 사용하여 명령 사이의 출력 진행 상황을 보았습니다.

데이터 세트를 가져 오려면 Pentaho Data Integration을 사용하여 ETL을 프로그래밍 할 수 있습니다.


0

아마도 이것은 또한 당신을 도울 수 있습니다.

  1. 먼저 파일 조옮김을 사용할 수 있습니다 ( /programming/1729824/an-efficient-way-to-transpose-a-file-in-bash 중 하나 )
  2. sort 명령으로 첫 번째 열을 정렬하십시오.
  3. 다시 바꿉니다.

전의:

$ echo "ID M2 M5 M8 M1 M3 M9 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln" | awk '
{ 
    for (i=1; i<=NF; i++)  {
        a[NR,i] = $i
    }
}
NF>p { p = NF }
END {    
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++){
            str=str" "a[i,j];
        }
        print str
    }
}' | sort -n | awk '
{ 
    for (i=1; i<=NF; i++)  {
        a[NR,i] = $i
    }
}
NF>p { p = NF }
END {    
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++){
            str=str" "a[i,j];
        }
        print str
    }
}'
ID M1 M2 M3 M5 .....M7000000 M8 M9
Animal1 1 1 0 0 .....1 2 2
Animal2 0 0 1 1 .....0 2 1
Animal3 1 2 2 1 .....0 0 1
.       
.       
.       
.       
Animaln    
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.