我有一个非常大的文本文件(> 80Gb)。它包含制表符分隔的值。我只对一栏感兴趣。对于该特定列,我希望得到reverse percentile ~10个阈值。所以基本上,我的问题看起来像这样:“列x的值低于$ threshold的行的百分比是多少?”。阈值大致为1,5,10,100,500,1000。 样本数据:
dontcare dontcare interesting
1 10 502
2 10 0
3 10 100
4 10 23
5 10 5
在上述情况下,我想问一下“低于500的值的百分比是多少?”答案是80%。
我该怎么做?
注意:
df[df < threshold].shape(0) / total_length
)花费的时间太长。几个小时后我停止了计算。我猜~1h就没事了。wc -l <filename>
和df = pd.read_csv(filename, sep='\t', header=None); print(pandasdataframe)
产生了不同数量的行,让我感到惊讶。 (不过我是熊猫新手。)修改
以下答案是正确的。我想出了下面的脚本。仅供参考,读取预过滤的文件(仅一列,<10G)花费1小时2小时并且读取原始文件(5个小组,大于80G)花费1小时16分钟。为简单起见,我不会预先过滤文件。在我的测试中,mawk比gawk好2倍。我使用NR
代替(NR-1)
,因为没有标题行。
#!/bin/bash
FILENAME=$1
COL=$2 # one-based
AWK_CMD=mawk
THRESHOLDS="0 5 10 20 50 100 200 300 400 500 1000"
[ "$#" -ne 2 ] && { echo >&2 "usage: $0 <filename> <one-based-col>"; exit 1; }
# check if awk cmd exists
command -v $AWK_CMD >/dev/null 2>&1 || { echo >&2 "Cannot find $AWK_CMD. Please install and/or put it into your \$PATH."; exit 1; }
# constuct final cmd
CMD="$AWK_CMD 'BEGIN { total=0;"
for t in $THRESHOLDS; do
# set init vars to zero
CMD="${CMD} n$t=0;"
done
CMD="${CMD}}; { total+=\$$COL}; "
for t in $THRESHOLDS; do
# increment depending on threshold
CMD="${CMD} {if (\$$COL>$t) {n$t+=1}} ;"
done
CMD="${CMD} END { print \"mean: \" total/NR; "
for t in $THRESHOLDS; do
# output percentage
CMD="${CMD} print \"above$t: \" n$t/NR*100 ;"
done
CMD="${CMD} }' $FILENAME"
# echo $CMD
eval $CMD # backticks and $() won't work here
答案 0 :(得分:3)
我建议使用awk来执行此操作:
awk 'NR > 1 && $3 < 500 { ++n } END { if (NR > 1) print n / (NR - 1) * 100 }' file
对于第三个字段小于500的第一个之后的所有行,增加n
。处理完文件后,只要读取了一个或多个记录,就打印百分比(这样可以避免除以0)。