하루 최고 습도를 기준으로 대용량 CSV 파일을 필터링하는 방법은 무엇입니까?

하루 최고 습도를 기준으로 대용량 CSV 파일을 필터링하는 방법은 무엇입니까?

수백만 행의 데이터가 있으므로 스프레드시트를 통해 이 작업을 수행할 수 없습니다. 일부 데이터 행에는 데이터가 없으므로 이러한 데이터 행을 건너뛰어야 합니다. 데이터는 .CSV 형식입니다. 모든 Unix 도구를 환영합니다. 구분 기호 ""로 인해 AWK일 수도 있습니다.

그것은 마치

awk -F " " '{ print $1 $2 $3 $4}' filename.csv

하지만 매일 가장 높은 습도를 얻는 방법은 무엇입니까? 한 가지 옵션이 있지만 작동하지 않습니다.

awk -F, 'NR==1 {next} {date=$1; humidity=$2; if (!max[date] || humidity > max[date]) {max[date]=humidity; line[date]=$0}} END {for (date in line) print line[date]}' filename.csv

데이터(Airthings View Plus - 기기에서)

recorded HUMIDITY %TEMP °C
2023-08-14 23:55:48 97.01 14.65
2023-08-14 23:55:50

2023-08-14 23:58:14 97.07 14.63
2023-08-14 23:58:16

2023-08-15 0:00:46 97.02 14.62
2023-08-15 0:00:48

2023-08-15 0:03:14 97.06 14.62
2023-08-15 0:03:16

헤드 실제 데이터

recorded,HUMIDITY %,TEMP °C
2023-08-14 16:55:56,97.64,14.62
2023-08-14 16:55:58,,
2023-08-14 16:58:13,97.41,14.76
2023-08-14 16:58:15,,
2023-08-14 17:00:45,97.04,14.88
2023-08-14 17:00:47,,
2023-08-15 17:03:12,96.78,15.26
2023-08-15 17:03:14,,
2023-08-15 17:05:45,96.59,14.89

원하는 출력

recorded HUMIDITY %TEMP °C
2023-08-14 23:58:14 97.07 14.63
2023-08-15 0:03:14 97.06 14.62

운영 체제: 데비안 12 리눅스

답변1

EX.3.feb.2024 - hum.t.p.day.csv참고: 이제 Google Docs에서 전체 OP를 사용하여 이러한 접근 방식을 시도해 보았지만 이 csvsql접근 방식은 미학적으로 매력적이기는 하지만괴로운느림(Miller 솔루션보다 약 600배 느림)

귀하의 예를 들어

$ cat input.csv
recorded,HUMIDITY %,TEMP °C
2023-08-14 16:55:56,97.64,14.62
2023-08-14 16:55:58,,
2023-08-14 16:58:13,97.41,14.76
2023-08-14 16:58:15,,
2023-08-14 17:00:45,97.04,14.88
2023-08-14 17:00:47,,
2023-08-15 17:03:12,96.78,15.26
2023-08-15 17:03:14,,
2023-08-15 17:05:45,96.59,14.89

csvsql그런 다음 Python 기반을 사용하십시오.csvkit:

$ csvsql --query '
    SELECT recorded,MAX("HUMIDITY %") AS "HUMIDITY %","TEMP °C" FROM input \
    WHERE "HUMIDITY %" NOT NULL GROUP BY DATE(recorded)
' input.csv
recorded,HUMIDITY %,TEMP °C
2023-08-14 16:55:56.000000,97.64,14.62
2023-08-15 17:03:12.000000,96.78,15.26

표 형식 출력의 경우 결과를 파이프합니다 csvformat -T.


또는 꾸미기-정렬-장식 해제 방법을 사용하세요.밀러

$ mlr --csvlite filter '!is_empty(${HUMIDITY %})' then \
    put '$day = splitnvx($recorded, " ")[1]' then \
    top -a -F -f 'HUMIDITY %' -g day then \
    cut -x -f day input.csv
recorded,HUMIDITY %,TEMP °C
2023-08-14 16:55:56,97.64,14.62
2023-08-15 17:03:12,96.78,15.26

이 경우 테이블 형식으로 출력하려면 --csvlite로 변경하십시오 --icsvlite --opprint.

답변2

AWK

$ awk -F',' 'NR>1{arr[$1]=arr[$1]>$2?arr[$1]:$2} END{for (i in arr) print i "," arr[i]}' ~/test.txt

산출

2023-08-14,97.07
2023-08-15,99.06

입력하다

$ cat ~/test.txt
recorded,HUMIDITY,TEMPC
2023-08-14,97.01,14.65
2023-08-14,90.01,19.65
2023-08-14,97.07,14.63
2023-08-15,97.02,14.60
2023-08-15,97.06,14.68
2023-08-15,99.06,14.62
2023-08-15,59.06,10.62

답변3

정렬 명령을 사용할 수 있습니다. 샘플 데이터로 시작하세요.

$ cat infile
2023-08-14 23:55:48 97.01 14.65
2023-08-14 23:55:50

2023-08-14 23:58:14 97.07 14.63
2023-08-14 23:58:16

2023-08-15 0:00:46 97.02 14.62
2023-08-15 0:00:48

2023-08-15 0:03:14 97.06 14.62
2023-08-15 0:03:16

먼저 습도 및 온도 데이터가 없는 빈 줄과 짧은 줄을 제거합니다.

$ awk 'NF>2' infile

그런 다음 결과는 sort 명령으로 파이프됩니다.

$ awk 'NF>2' infile | sort -nr -t "," -k1,3
2023-08-15 0:03:14 97.06 14.62
2023-08-15 0:00:46 97.02 14.62
2023-08-14 23:58:14 97.07 14.63
2023-08-14 23:55:48 97.01 14.65

답변4

사용행복하다(이전 Perl_6)

~$ raku -MCSV::Parser -e 'my $file_handle = open $*ARGFILES, :r;     
                          my $parser = CSV::Parser.new(:$file_handle, :contains_header_row);  
                          my %accum;                                 
                          until $file_handle.eof {                   
                              my %ln-in = $parser.get_line();        
                              %accum.append: %ln-in{"recorded"}.words[0] => %ln-in{"HUMIDITY %"};  
                          };                                         
                          $file_handle.close;                        
                          put .key => .value.max for %accum.sort;'   file

Perl 계열의 프로그래밍 언어인 Raku로 작성된 답변입니다. Raku의 CSV::Parser모듈은 명령줄에서 로드되며 입력은 한 줄씩 읽혀집니다.

먼저 를 선언 $file_handle한 다음 을 선언하세요 $parser. 최종 %accum해시는 데이터를 캡처하는 데 사용됩니다. 중앙 until조건문 에서 get_line까지 행을 읽습니다 eof. 각 행에 대해 임시 %ln-in해시는 키/값 쌍으로 분해되며 날짜는 로 기록되고 key습도는 으로 기록됩니다 value. 키/값 쌍이 해시 값 append에 기록됩니다 .%accum

마지막 문에서 해시 %accum에는 .put.value.max

예제 출력:

2023-08-14  97.64
2023-08-15  97.24
2023-08-16  97.33
2023-08-17  97.91
2023-08-18  97.83
2023-08-19  97.74
2023-08-20  97.85
2023-08-21  98.27
2023-08-22  99.79
2023-08-23  99.74
2023-08-24  99.24
2023-08-25  98.82
2023-08-26  99.34
2023-08-27  99.99
2023-08-28  99.95
2023-08-29  96.76
2023-08-30  99.93
2023-08-31  99.99
2023-09-01  99.99
2023-09-02  97.43
2023-09-03  97.85
2023-09-04  98.2
2023-09-05  98.42
2023-09-06  98.37
2023-09-07  97.78
2023-09-08  98.4
2023-09-09  98.68
2023-09-10  98.86
2023-09-11  99.06
2023-09-12  99.16
2023-09-13  99.26
2023-09-14  99.29
2023-09-15  98.66
2023-09-16  98.86
2023-09-17  98.95
2023-09-18  97.05
2023-09-19  98.59
2023-09-20  98.79
2023-09-21  99.08
2023-09-22  99.19
2023-09-23  99.34
2023-09-24  99.04
2023-09-25  98.83
2023-09-26  98.03
2023-09-30  97.06
2023-10-01  96.42
2023-10-04  95.12
2023-10-05  95.54
2023-10-10  89.17
2023-10-12  92.46
2023-10-28  61.28
2023-10-29  63.81
2023-10-30  72.65
2023-10-31  83.58
2023-11-01  80.13
2023-11-02  73.02
2023-11-03  84.29
2023-11-04  88.51
2023-11-05  88.78
2023-11-06  88.92
2023-11-07  88.42
2023-11-08  84.67
2023-11-09  82.41
2023-11-10  88.76
2023-11-11  88.49
2023-11-12  81.66
2023-11-13  77.46
2023-11-14  75.9
2023-11-15  68.31
2023-11-16  64.05
2023-11-17  58.46
2023-11-18  70.53
2023-11-19  74.63
2023-11-20  80.45
2023-11-21  68.86
2023-11-22  74.33
2023-11-23  78.19
2023-11-24  76.35
2023-11-25  53.12
2023-11-26  55.34
2023-11-27  53.97
2023-11-28  73.23
2023-11-29  73.78
2023-11-30  68.54
2023-12-01  65.52
2023-12-02  60.14
2023-12-03  57.08
2023-12-04  56.14
2023-12-05  58.63
2023-12-06  69.79
2023-12-07  71.09
2023-12-08  67.39
2023-12-09  64.75
2023-12-10  75.76
2023-12-11  74.33
2023-12-12  71.79
2023-12-13  68.64
2023-12-14  66.75
2023-12-15  67.56
2023-12-16  77.84
2023-12-17  78.79
2023-12-18  76.41
2023-12-19  79.71
2023-12-20  73.87
2023-12-26  70.58
2023-12-27  70.97
2023-12-28  73.21
2023-12-29  74.73
2023-12-30  73.81
2023-12-31  63.24
2024-01-01  53.16
2024-01-02  54.76
2024-01-03  55.39
2024-01-04  57.09
2024-01-05  54.78
2024-01-06  55.84
2024-01-07  49.51
2024-01-08  65.82
2024-01-09  76.71
2024-01-10  77.09
2024-01-11  77.02
2024-01-12  71.6
2024-01-13  69.29
2024-01-14  69.79
2024-01-15  69.02
2024-01-16  58.51
2024-01-17  64.79
2024-01-18  70.11
2024-01-19  69.38
2024-01-20  52.53
2024-01-21  67.66
2024-01-22  78.08
2024-01-23  79.02
2024-01-24  78.58
2024-01-25  78.84
2024-01-26  70.76
2024-01-27  74.59
2024-01-28  79.74
2024-01-29  79.76
2024-01-30  78.77
2024-01-31  80.31
2024-02-01  80.34
2024-02-02  74.42

위의 코드는 각 키에 대해 여러 값을 누적하여 max마지막에만 출력합니다. 매우 큰 파일의 경우 이는 문제가 될 수 있습니다. 메모리 효율성을 향상시키기 위한 대안으로 Raku 코드는 append들어오는 행의 키/값 쌍을 확인한 다음 value요소가 1보다 큰지 즉시 확인합니다. 그렇다면 이 값을 단일 max값으로 줄이세요. 아래 코드는 위와 동일한 샘플 출력을 제공합니다.

~$ raku -MCSV::Parser -e 'my $file_handle = open $*ARGFILES, :r;
                          my $parser = CSV::Parser.new( :$file_handle, :contains_header_row); 
                          my %accum; 
                          until $file_handle.eof() { given $parser.get_line() -> %ln-in {  
                              my $ln-key = %ln-in{"recorded"}.words[0]; my $ln-value = %ln-in{"HUMIDITY %"};
                              %accum.append: $ln-key => $ln-value;
                              %accum{$ln-key} = %accum{$ln-key}.max if %accum{$ln-key}.elems > 1 }
                         }; 
                         $file_handle.close; 
                         put .key => .value for %accum.sort;'  file

https://github.com/tony-o/perl6-csv-parser
https://raku.org

관련 정보