0

我有一个包含 3 列的 CSV 文件,如下所示:

a,b,c
1,1,2
1,3,5
1,5,7
.
.
2,3,4
2,1,5
2,4,7

我希望输出像

a,b,c
1,5,7
1,3,5
1,1,2
.
.
2,4,7
2,3,4
2,1,5

即,对于a 列中的每个元素,我只想拥有前20 行(20 个最高'b' 值)行。请原谅我拙劣的解释。到目前为止我已经尝试过了,但这并没有给我所需的输出:

import csv
import heapq
from itertools import islice
csvout = open ("output.csv", "w")
writer = csv.writer(csvout, delimiter=',',quotechar='"', lineterminator='\n', quoting=csv.QUOTE_MINIMAL)
freqs = {}
with open('input.csv') as fin:
    csvin = csv.reader(fin)
    rows_with_mut = ([float(row[1])] + row for row in islice(csvin, 1, None) if row[2])
    for row in rows_with_mut:
        cnt = freqs.setdefault(row[0], [[]] * 20)
        heapq.heappushpop(cnt, row)

for assay_id, vals in freqs.iteritems():
    output = [row[1:] for row in sorted(filter(None, vals), reverse=True)]
    writer.writerows(output)
4

2 回答 2

2

由于文件仅在 a 列上排序,因此您还必须在 b 和 c 列上对其进行排序。我建议使用natsort,按升序或降序对文件进行排序,而不是循环遍历它并为 a 列的每个值打印 20 行。

类似于以下内容:

import natsort

with open('myfile.csv', 'r') as inFile:
    lines = inFile.readlines()
    sortedList = reversed(natsort.natsorted(lines))
    #alternatively, you might want to try natsort.versorted() which is used for version numbers
    counter = 0
    prevAVal=currentAval=1
    for line in sortedList:
        currentAVal = ",".split(line)[0]
        if currentAVal != prevAval:
            counter = 0
        if counter < 20 :
                print line
        counter = counter + 1
        prevAVal=currentAVal
于 2014-10-15T00:00:08.793 回答
1

关于投票的风险,您可以使用一个简单的 bash 脚本:

#!/bin/bash
all=$(cat) #read from stdin
echo "$all" | head -n 1 #echo the header of the file
allt=$(echo "$all" | tail -n +2) #remove the header from memory
avl=$(echo "$allt" | cut -d ',' -f 1 | sort | uniq) #find all unique values in the a column
for av in $avl #iterate over these values
do
    echo "$allt" | grep "^$av," | sort -t$',' -k2nr | head -n 20 #for each value, find all lines with that value and sort them, return the top 20...
done

您可以使用以下命令在命令行中运行它:

bash script.sh < data.csv

它将在终端上打印结果...

示例

如果使用您的样本值(没有“点”行),则获得:

user@machine ~> bash script.sh < data.csv 
a,b,c
1,5,7
1,3,5
1,1,2
2,4,7
2,3,4
2,1,5

如果要将结果写入文件(例如data2.csv),请使用:

bash script.sh < data.csv > data2.csv

不要读写同一个文件:不要运行bash script.sh < data.csv > data.csv

于 2014-10-14T23:52:19.650 回答