![하루 최고 습도를 기준으로 대용량 CSV 파일을 필터링하는 방법은 무엇입니까?](https://linux55.com/image/228775/%ED%95%98%EB%A3%A8%20%EC%B5%9C%EA%B3%A0%20%EC%8A%B5%EB%8F%84%EB%A5%BC%20%EA%B8%B0%EC%A4%80%EC%9C%BC%EB%A1%9C%20%EB%8C%80%EC%9A%A9%EB%9F%89%20CSV%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20%ED%95%84%ED%84%B0%EB%A7%81%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
수백만 행의 데이터가 있으므로 스프레드시트를 통해 이 작업을 수행할 수 없습니다. 일부 데이터 행에는 데이터가 없으므로 이러한 데이터 행을 건너뛰어야 합니다. 데이터는 .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