대용량 파일에서 값이 없는 CSV 필드 제거

대용량 파일에서 값이 없는 CSV 필드 제거

그래서 저는 CSV 파일을 매개변수로 받아들이고 고유 값이 2개 미만인 모든 필드를 제거하는 이 스크립트를 만들었습니다. 어차피 내가 다루는 데이터는 각 필드에 2개의 값이 있기 때문이다. 이것이 Reddit 데이터의 모습입니다.

기본적으로 제가 하는 일은 컷 루프를 사용하여 각 열을 반복한 다음 각 열을 고유하게 정렬한 다음 2보다 작으면 해당 열 번호를 저장하는 것입니다. 그런 다음 적어둔 모든 열 번호를 반복하고 이를 삭제하는 빅 컷 명령을 생성합니다.

문제는 대용량 파일을 처리할 때 실행 속도가 매우 느리다는 것입니다.

가능하다면 속도를 높이고 싶지만 고급 명령을 사용하는 데 익숙하지 않습니다. 누군가 나에게 이것을 달성하는 더 빠른 방법을 보여줄 수 있다면 나는 기쁠 것입니다! 감사해요.

암호:

#!/bin/bash

#find number of fields
num_items=$(cat $1 | head -n 1 | grep -o , | wc -w)
num_items=$((num_items + 0))


echo "Searching all $num_items columns for redundancy"

cols=()

command="-f"
for ((i = 1; i < $num_items; i++))
do
    num_vals=$(cat $1 | cut -d, -f$i | sort -u | wc -w)
    x=$(($num_vals+0))

    #remove column if it has less than 2 values in its column
    #lt 3 as we want to discard the field name at the top
    if [ $x -lt 3 ]
    then
        cols+=("$i")
    fi
    bit="$i-$i,"
    command="${command}${bit}"
done
command="${command}$num_items-$num_items"
echo ""
for col in "${cols[@]}"; do
    sed_reg="s/$col-$col,//"
    command=$(echo "$command" | sed $sed_reg)
    echo "col $col has been removed"
done

command="cut -d, ${command} $1"

$command > pruned_cols.csv

더 작은 샘플 데이터:https://ufile.io/27bm31d6

~70,000줄. 견본:https://ufile.io/qvglxajr

시스템: zsh를 사용하는 macOS

답변1

이것이 당신에게 얼마나 도움이 되는지 확인해 보세요:

$ cut --complement -d, -f$(awk -F, '
NR > 1  {for (i=1; i<=NF; i++)  CNT[i, $i]++
        }
END     {for (c in CNT) if (CNT[c] == (NR-1))   {split (c, T, SUBSEP)
                                                 printf "%s%d", DL, T[1]
                                                 DL = ","
                                                }
        }
' /tmp/small_data.csv)  /tmp/small_data.csv

귀하의 cut버전에 해당 옵션이 있다고 가정합니다 --complement. 그렇지 않으면 인쇄 논리를 반대로 합니다. 해당 섹션에서 실패하면 awk행별 처리를 유지하세요.NREND

모든 행(제목 제외)의 모든 필드를 살펴보고 고유한 콘텐츠를 계산합니다. 해당 END섹션 에서 CNT행 수에서 헤더를 뺀 것과 같은 경우(즉, 필드의 모든 행에서 동일한 내용이 있는 경우) 인덱스를 분할하고 필드 번호를 인쇄합니다.

관련 정보