문제

다음 표로 표시할 수 있는 컴퓨터 시뮬레이션을 통해 생성된 종단적 데이터 세트가 있습니다('var'은 변수입니다).

time subject var1 var2 var3
t1   subjectA  ...
t2   subjectB  ...

그리고

subject   name
subjectA  nameA
subjectB  nameB

그러나 생성된 파일은 다음과 유사한 형식으로 데이터 파일을 작성합니다.

time t1 
  description
subjectA nameA
  var1 var2 var3
subjectB nameB
  var1 var2 var3
time t2
  description
subjectA nameA
  var1 var2 var3
subjectB nameB
  var1 var2 var3
...(and so on)

나는 (python) 스크립트를 사용하여 이 출력 데이터를 일반 텍스트 파일로 처리하여 R, Python, SQL 또는 awk/grep으로 가져와서 정보를 추출할 수 있도록 했습니다. 단일 쿼리(SQL 표기법에서 데이터가 테이블로 변환된 후)는 다음과 같습니다.

SELECT var1, var2, var3 FROM datatable WHERE subject='subjectB'

이러한 각 데이터 파일은 각각 ~100MB(그리고 수백 개가 있음)일 수 있고 일반 텍스트 파일을 만드는 데 시간이 많이 걸리고 중복 정보로 인해 추가 하드 드라이브 공간을 차지하므로 더 효율적인 솔루션이 있는지 궁금합니다.이상적으로는 추가 일반 텍스트 파일을 만들지 않고 원본 데이터 세트와 직접 상호 작용하여 원하는 정보를 추출하는 것입니다.이러한 작업을 위한 더 간단한 awk/perl 솔루션이 있습니까?나는 Python의 텍스트 처리에 능숙하지만 awk 기술은 초보적이며 Perl에 대한 실무 지식이 없습니다.이러한 도구나 다른 도메인별 도구가 더 나은 솔루션을 제공할 수 있는지 궁금합니다.

감사해요!

추신:와, 모두 고마워요!모든 사람의 답변을 선택할 수 없어서 @fm을 선택할 수 없습니다.감사해요.내 Python 스크립트는 필터링 단계가 없는 코드와 유사합니다.하지만 당신의 조직은 깨끗합니다.@PP:나는 이미 grep에 능숙하다고 생각했지만 분명히 그렇지 않았습니다!이것은 매우 도움이 됩니다...하지만 '시간'을 출력에 혼합하면 파악이 어려워지는 것 같습니다(제 예에서는 가능한 추출 시나리오로 포함하지 못했습니다!).그게 내 잘못이야).@ghostdog74:이건 정말 환상적이에요...하지만 'subjectA'를 얻기 위해 줄을 수정하는 것은 간단하지 않았습니다...(그 동안 awk에 대해 더 많이 읽을 것이고 나중에 grok을 하게 되기를 바랍니다).@weismat:잘 명시되어 있습니다.@S.Lott:이것은 매우 우아하고 유연합니다. Python(ic) 솔루션을 요청한 것은 아니지만 이는 PP에서 제안한 구문 분석, 필터 및 출력 프레임워크에 완벽하게 들어맞으며 다양한 쿼리를 수용하여 서로 다른 쿼리를 추출할 수 있을 만큼 충분히 유연합니다. 이 계층적 파일의 정보 유형입니다.

다시 한 번 모든 분들께 감사드립니다. 정말 감사드립니다.

도움이 되었습니까?

해결책

이것이 파이썬 생성기의 모든 것입니다.

def read_as_flat( someFile ):
    line_iter= iter(someFile)
    time_header= None
    for line in line_iter:
        words = line.split()
        if words[0] == 'time':
            time_header = [ words[1:] ] # the "time" line
            description= line_iter.next()
            time_header.append( description )
        elif words[0] in subjectNameSet:
            data = line_iter.next()
            yield time_header + data

이것을 표준 파이썬 반복기처럼 사용할 수 있습니다

for time, description, var1, var2, var3 in read_as_flat( someFile ):
    etc.

다른 팁

원하는 것이 특정 주제와 일치할 때 var1, var2, var3이라면 다음 명령을 시도해 볼 수 있습니다.


  grep -A 1 'subjectB'

그만큼 -A 1 명령줄 인수는 grep에게 일치하는 줄과 일치하는 줄 다음의 한 줄을 인쇄하도록 지시합니다(이 경우 변수는 제목 뒤의 줄에 옵니다).

당신은 -E 정규식에 대한 grep 검색을 수행하고 제목 검색을 줄 시작 부분에 고정하는 옵션(예: grep -A 1 -E '^subjectB').

마지막으로 출력은 이제 원하는 제목 줄과 변수 줄로 구성됩니다.제목 줄을 숨길 수도 있습니다:


  grep -A 1 'subjectB' |grep -v 'subjectB'

그리고 변수 라인을 처리하고 싶을 수도 있습니다:


  grep -A 1 'subjectB' |grep -v 'subjectB' |perl -pe 's/ /,/g'

가장 좋은 옵션은 컴퓨터 시뮬레이션을 수정하여 직사각형 출력을 생성하는 것입니다. 그렇게 할 수 없다고 가정하면 다음은 다음과 같습니다.

R, SQL 등의 데이터를 사용하려면 계층 적에서 직사각형으로 변환해야합니다. 전체 파일을 직사각형 데이터 세트로 변환 할 수있는 구문 분석기가 이미있는 경우 대부분의 방법입니다. 다음 단계는 원치 않는 데이터 레코드를 필터링 할 수 있도록 파서에 유연성을 추가하여 추가 유연성을 추가하는 것입니다. 파일 변환기가있는 대신 데이터 추출 유틸리티가 있습니다.

아래의 예는 Perl에 있지만 Python에서 동일한 작업을 수행 할 수 있습니다. 일반적인 아이디어는 (a) 구문 분석, (b) 필터링 및 (c) 출력 사이의 깨끗한 분리를 유지하는 것입니다. 이렇게하면 유연한 환경이있어 즉각적인 데이터 크런치 요구에 따라 다양한 필터링 또는 출력 방법을 쉽게 추가 할 수 있습니다. 유연성이 향상되기 위해 매개 변수 (명령 줄 또는 구성 파일)를 수락하기 위해 필터링 메소드를 설정할 수도 있습니다.

use strict;
use warnings;

read_file($ARGV[0], \&check_record);

sub read_file {
    my ($file_name, $check_record) = @_;
    open(my $file_handle, '<', $file_name) or die $!;
    # A data structure to hold an entire record.
    my $rec = {
        time => '',
        desc => '',
        subj => '',
        name => '',
        vars => [],
    };
    # A code reference to get the next line and do some cleanup.
    my $get_line = sub {
        my $line = <$file_handle>;
        return unless defined $line;
        chomp $line;
        $line =~ s/^\s+//;
        return $line;
    };
    # Start parsing the data file.
    while ( my $line = $get_line->() ){
        if ($line =~ /^time (\w+)/){
            $rec->{time} = $1;
            $rec->{desc} = $get_line->();
        }
        else {
            ($rec->{subj}, $rec->{name}) = $line =~ /(\w+) +(\w+)/;
            $rec->{vars} = [ split / +/, $get_line->() ];

            # OK, we have a complete record. Now invoke our filtering
            # code to decide whether to export record to rectangular format.
            $check_record->($rec);
        }
    }
}

sub check_record {
    my $rec = shift;
    # Just an illustration. You'll want to parameterize this, most likely.
    write_output($rec)
        if  $rec->{subj} eq 'subjectB'
        and $rec->{time} eq 't1'
    ;
}

sub write_output {
    my $rec = shift;
    print join("\t", 
        $rec->{time}, $rec->{subj}, $rec->{name},
        @{$rec->{vars}},
    ), "\n";
}

당신이 게으르고 RAM이 충분하다면, 나는 당신이 필요로하는 한 파일 시스템 대신 RAM 디스크에서 작업 할 것입니다.
현재 알고리즘을 다른 언어로 다시 코딩하는 경우 Perl 또는 AWK가 Python보다 빠를 것이라고 생각하지 않습니다.

awk '/time/{f=0}/subjectB/{f=1;next}f' file
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top