그래서 저는 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
행별 처리를 유지하세요.NR
END
모든 행(제목 제외)의 모든 필드를 살펴보고 고유한 콘텐츠를 계산합니다. 해당 END
섹션 에서 CNT
행 수에서 헤더를 뺀 것과 같은 경우(즉, 필드의 모든 행에서 동일한 내용이 있는 경우) 인덱스를 분할하고 필드 번호를 인쇄합니다.