1

非常に大きな tsv ファイルがあり、いくつかの列を削除する必要があります。私は CSV モジュールを見つけました。また、似たような質問に対する以下のような回答もあります (以下のスクリプトを参照)。それでも、広範囲の列を削除する必要があり、削除する各列のすべてのインデックスを入力したくありません。つまり、689513 列のファイルから、列 628715 から 650181 を削除し、列 653321 から 689513 も削除したいと考えています。 653321 から 689613、または同等の 653321 からファイルの末尾まで)。基本的な質問で申し訳ありません。私はスクリプトを作成するのが初めてで、道に迷っています...そしてCSVモジュールのページでは、列範囲の削除について詳しく説明していません。R でこれを実行しようとしましたが、最初のセル エントリが空白です (コードの下のサンプル リストを参照)。私のファイルは tsv タブ区切りファイルですが、区切り文字を \t に設定するコマンドを使用して修正できるものを集めています。どんな助けでも大歓迎です!!! (注: 残念ながら、列の名前にコロンを付ける必要があります。つまり、2L:1274 は完全に 1 つの列の名前です)。

import csv
with open("source","rb") as source:
rdr= csv.reader( source )
with open("result","wb") as result:
    wtr= csv.writer( result )
    for r in rdr:
        wtr.writerow( (r[0], r[1], r[3], r[4]) )

2L:1274 2L:2425 2L:2853 3L:4    3L:5    3L:7
indivBCsusceptiblePL7A10_TATAGT NA  NA  NA  NA  NA  NA
indivBCsusceptiblePL7A11_CCTGAA NA  5   NA  NA  NA  NA
indivBCsusceptiblePL7A12_CAATAT NA  NA  6   7   8   9
indivBCsusceptiblePL7A1_CCGAAT  NA  NA  NA  NA  NA  NA
4

5 に答える 5

2

delリストのスライスを削除するために使用できます。

with open('in.tsv', 'r') as fin, open('out.tsv', 'w') as fout:
    reader = csv.reader(fin, dialect='excel-tab')
    writer = csv.writer(fout, dialect='excel-tab')
    for row in reader:
        # delete indices in reverse order to avoid shifting earlier indices
        del row[653321:689513+1]
        del row[628715:650181+1]
        writer.writerow(row)
于 2012-10-02T15:33:53.070 に答える
1

これは、Python を使用して非常に少ないメモリで実行できます。

最初に、tsv 形式を記述する方言を定義します。詳細については、方言に関するドキュメントを参照してください。

class TsvDialect(csv.Dialect):
    delimiter = '\t'
    quoting = csv.QUOTE_NONE
    escapechar = None

# you can just pass this class around, or you can register it under a name
csv.register_dialect('tsv', TsvDialect)

次に、各行をたどって新しい tsv にコピーできます。

with open('source.tsv', 'rb') as src, open('result.tsv', 'wb') as res:
    csrc = csv.reader(src, dialect='tsv')
    cres = csv.writer(res, dialect='tsv')
    for row in csrc:
        cres.writerow(row)

これは単純なコピーを行います。いくつかの行だけが必要なので、それらだけをコピーしましょう。

Python のリストのインデックスはゼロです (最初の列は列 1 ではなく列 0 です)。また、インデックス スライスには最後の項目が含まれません (wholelist[:2]は と同じ[wholelist[0], wholelist[1]]です)。オフ バイ ワン エラーを回避するために、これらの点に注意してください。

with open('source.tsv', 'rb') as src, open('result.tsv', 'wb') as res:
    csrc = csv.reader(src, dialect='tsv')
    cres = csv.writer(res, dialect='tsv')
    for row in csrc:
        # remove [628714:650181] and [653320:689512]
        newrow = row[:628714] # columns before 628714
        newrow.extend(row[650181:653320]) # columns between 650180 and 653320
        cres.writerow(newrow)

または、必要な列を新しい行にコピーする代わりに、不要な列を削除することで、コードの明瞭さを犠牲にしてメモリを節約できます。

    for row in csrc:
        # remove [628714:650181] and [653320:689512]
        # be sure to remove in reverse order!
        del row[653320:689512]
        del row[628714:650181]
        cres.writerow(row)

これを非常に頻繁に行う必要がある場合は、列の切り取り (快適なインデックス付けを使用したいずれかの方法) を関数に抽象化できます。

csvkit python ライブラリとコマンド ライン ツール、特にそのコマンド ライン ツールcsvcutも参照してください。これは、コマンド ラインから必要なことを正確に実行するように見えます。

于 2012-10-02T16:29:03.243 に答える
0

Linuxを使用していますか?次に、ハズルを保存し、csvtoolシェルから使用します。

 csvtool col 1-500,502-1000 input.csv > output.csv

区切り文字などを設定することもできます。入力するだけですcsvtool --help。非常に使いやすいです。

于 2012-10-02T16:40:54.207 に答える
0

2 GB以上のRAMを使用すると、データセットをメモリにロードし、必要な列を削除して、内容をファイルに書き込むことができるはずです。これは、RまたはPythonで簡単に実行できます。Rの場合:

dat = read.table("spam.tsv", ...)
dat = dat[-c(1,5)] # delete row 1 and 5
write.csv(dat, ....)

applyこれをチャンクで行うには、ループまたはループのいずれかを使用して簡単に行うことができforます。私はapplyスタイルを使用します:

read_chunk = function(chunk_index, chunk_size, fname) {
    dat = read.table(fname, nrow = chunk_size, skip = (chunk_id - 1) * chunk_size, ...)
    dat = dat[-c(1,5)] # delete row 1 and 5
    write.csv(dat, append = TRUE, ....)    
}

tot_no_lines = 10000 # for example
chunk_size = 1000
sapply(1:(tot_no_lines / chunk_size), read_chunk)

これはインスピレーションとして役立つRスタイルのコードであり、機能するRコードではないことに注意してください。

于 2012-10-02T15:15:01.500 に答える
0

出力行を動的に作成できます。

for r in rdr:
    outrow = []
    for i in range(0, 628714):
       outrow.append(r[i])
    for i in range(650181, 653320):
       outrow.append(r[i])
    wtr.writerow( outrow )

次の行に沿って、入力行 r のスライスを使用して、これをさらに簡潔に行うことができると思います。

 outrow = r[0:628714)
 outrow.extend(r[650181:653320)
 wrt.writerow( outrow )

実行するのはおそらく最速ではありませんが、書くのは確かに簡単です。

于 2012-10-02T15:22:42.653 に答える