Pythonでファイルの最初のN行を読み取る


150

指定したサイズにトリミングしたい大きな生データファイルがあります。私は.net c#の経験がありますが、Pythonでこれを行い、物事を簡素化して興味をそそります。

Pythonでテキストファイルの最初のN行を取得するにはどうすればよいですか?使用しているOSは実装に影響しますか?


コマンドライン引数としてnを指定できます
Nons

回答:


240

Python 2

with open("datafile") as myfile:
    head = [next(myfile) for x in xrange(N)]
print head

Python 3

with open("datafile") as myfile:
    head = [next(myfile) for x in range(N)]
print(head)

これが別の方法です(Python 2とPythonの両方)

from itertools import islice
with open("datafile") as myfile:
    head = list(islice(myfile, N))
print head

1
本当にありがとうございます。2つの違いは何ですか?(パフォーマンス、必要なライブラリ、互換性などに関して)?
ラッセル

1
パフォーマンスは似ていると思いますが、おそらく最初のほうが少し速いでしょう。ただし、ファイルに少なくともN行がない場合、最初の行は機能しません。パフォーマンスを測定するには、それを使用するいくつかの一般的なデータに対してパフォーマンスを測定するのが最善です。
John La Rooy、2009年

1
withステートメントはPython 2.6で機能し、2.5では追加のimportステートメントが必要です。2.4以前の場合は、try ... exceptブロックを使用してコードを書き直す必要があります。文体的には、最初のオプションを優先しますが、前述のように、2番目は短いファイルに対してより堅牢です。
Alasdair

1
それはCで実装されているようisliceはおそらく高速です
アリス・パーセル

22
ファイルが少ないし、N行があれば、これはあなたが処理しなければならないことを呼び出すとStopIteration例外が発生しますことを心に持っている
イリアン・イリーブ

19
N = 10
with open("file.txt", "a") as file:  # the a opens it in append mode
    for i in range(N):
        line = next(file).strip()
        print(line)

23
f = open("file")ファイルを閉じるための例外処理なしで、いつでも私はうんざりしています。Pythonicの方法でファイルを処理するには、コンテキストマネージャを使用します。つまり、withステートメントを使用します。これについては、入出力Pythonチュートリアルで説明しています。"It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way."
マークミコフスキー2013年

1
なぜファイルを追加モードで開くのですか?
AMC

13

最初の行をすばやく読みたい場合で、パフォーマンスを気にしない場合は、.readlines()which を使用してリストオブジェクトを返し、リストをスライスできます。

たとえば、最初の5行の場合:

with open("pathofmyfileandfileandname") as myfile:
    firstNlines=myfile.readlines()[0:5] #put here the interval you want

注:ファイル全体が読み込まれるため、パフォーマンスの観点からは最適ではありませんが、使いやすく、書き込みが速く、覚えやすいので、一度だけ計算を実行する場合は非常に便利です。

print firstNlines

他の回答と比較した1つの利点は、行の範囲を簡単に選択できることです。たとえば、最初の10行[10:30]または最後の10 行をスキップしたり、[:-10]偶数行のみを取得したりできます[::2]


2
一番上の答えはおそらくもっと効率的ですが、これは小さなファイルの魅力のように機能します。
T.Chmelevskij 2015年

2
これは実際にファイル全体を最初にリスト(myfile.readlines())に読み取り、次にその最初の5行をスプライスすることに注意してください。
AbdealiJK 2016年

2
これは避けてください。
anilbey

1
これを使用する理由はありません。非常に効率的なソリューションよりも単純ではありません。
AMC

@AMCフィードバックに感謝します。最初の行をすばやく確認する必要がある場合は、コンソールでデータを探索するために使用します。コードを書く時間を節約するだけです。
GM

9

私が行うことは、を使用してN行を呼び出すことですpandas。私はパフォーマンスは最高ではないと思いますが、例えばN=1000

import pandas as pd
yourfile = pd.read('path/to/your/file.csv',nrows=1000)

3
nrows1000に設定でき、ファイル全体が読み込まれないオプションを使用することをお勧めします。pandas.pydata.org/pandas-docs/stable/generated/…一般に、pandasには、これと他の大きなファイル用のメモリ節約テクニックがあります。
philshem 2017

はい、そうです。修正するだけです。間違いでごめんなさい。
Cro-Magnon 2017

1
sep列区切り文字を定義するために追加することもできます(非csvファイルでは発生しないはずです)
philshem

1
@ Cro-Magnon pandas.read()ドキュメントで関数を見つけることができません。この件に関する情報を知っていますか?
AMC

6

ファイルオブジェクトによって公開された行数を読み取る特定の方法はありません。

最も簡単な方法は次のようになると思います:

lines =[]
with open(file_name) as f:
    lines.extend(f.readline() for i in xrange(N))

これは私が実際に意図したものです。とはいえ、リストに各行を追加します。ありがとうございました。
artdanil 2009年

4

gnibblerのトップ投票の回答(2009年11月20日0:27)に基づく:このクラスは、head()およびtail()メソッドをファイルオブジェクトに追加します。

class File(file):
    def head(self, lines_2find=1):
        self.seek(0)                            #Rewind file
        return [self.next() for x in xrange(lines_2find)]

    def tail(self, lines_2find=1):  
        self.seek(0, 2)                         #go to end of file
        bytes_in_file = self.tell()             
        lines_found, total_bytes_scanned = 0, 0
        while (lines_2find+1 > lines_found and
               bytes_in_file > total_bytes_scanned): 
            byte_block = min(1024, bytes_in_file-total_bytes_scanned)
            self.seek(-(byte_block+total_bytes_scanned), 2)
            total_bytes_scanned += byte_block
            lines_found += self.read(1024).count('\n')
        self.seek(-total_bytes_scanned, 2)
        line_list = list(self.readlines())
        return line_list[-lines_2find:]

使用法:

f = File('path/to/file', 'r')
f.head(3)
f.tail(3)

4

これを行う最も直感的な2つの方法は次のとおりです。

  1. ファイルを行ごとに、行のbreak後に繰り返しますN

  2. next()メソッドNtimes を使用して、ファイルを行ごとに繰り返します。(これは基本的に、トップアンサーが行うことの異なる構文です)

これがコードです:

# Method 1:
with open("fileName", "r") as f:
    counter = 0
    for line in f:
        print line
        counter += 1
        if counter == N: break

# Method 2:
with open("fileName", "r") as f:
    for i in xrange(N):
        line = f.next()
        print line

肝心なのは、ファイル全体を使用しreadlines()たりenumerate、メモリに格納したりしない限り、多くのオプションがあります。


3

私自身で最も便利な方法:

LINE_COUNT = 3
print [s for (i, s) in enumerate(open('test.txt')) if i < LINE_COUNT]

リスト内包に基づくソリューション 関数open()は反復インターフェースをサポートしています。enumerate()はopen()をカバーし、タプル(インデックス、アイテム)を返します。次に、許容範囲内にあることを確認し(i <LINE_COUNTの場合)、結果を出力します。

Pythonをお楽しみください。;)


これは、のもう少し複雑な代替手段のよう[next(file) for _ in range(LINE_COUNT)]です。
AMC

3

最初の5行については、単に次のようにします。

N=5
with open("data_file", "r") as file:
    for i in range(N):
       print file.next()

2

(マニュアルで難解なものを検索せずに)インポートなしで機能し、Python 2.xバージョン(2.2から2.6)のかなりの範囲でtry / exceptおよび機能するものが必要な場合:

def headn(file_name, n):
    """Like *x head -N command"""
    result = []
    nlines = 0
    assert n >= 1
    for line in open(file_name):
        result.append(line)
        nlines += 1
        if nlines >= n:
            break
    return result

if __name__ == "__main__":
    import sys
    rval = headn(sys.argv[1], int(sys.argv[2]))
    print rval
    print len(rval)

2

非常に大きなファイルがあり、出力をnumpy配列にする場合は、np.genfromtxtを使用するとコンピューターがフリーズします。これは私の経験では非常に優れています:

def load_big_file(fname,maxrows):
'''only works for well-formed text file of space-separated doubles'''

rows = []  # unknown number of lines, so use list

with open(fname) as f:
    j=0        
    for line in f:
        if j==maxrows:
            break
        else:
            line = [float(s) for s in line.split()]
            rows.append(np.array(line, dtype = np.double))
            j+=1
return np.vstack(rows)  # convert list of vectors to array

非常に大きなファイルがあり、出力を派手な配列にしたい場合、これは非常にユニークな制限のセットですが、他の方法に勝る利点はありません。
AMC

1

Python 2.6から、IOベースクラスでより高度な関数を利用できるようになりました。したがって、上記の最高評価の回答は次のように書き換えられます。

    with open("datafile") as myfile:
       head = myfile.readlines(N)
    print head

(StopIteration例外がスローされないため、ファイルの行数がN未満であることを心配する必要はありません。)


25
ドキュメントによると、Nは読み取るバイト数であり、数ではありません
マークミコフスキー2013年

4
Nはバイト数です!
2014年

5
ワオ。不十分な命名について話します。関数名は言及してlinesいますが、引数はを参照していbytesます。
ArtOfWarfare 2015

0

これは私のために働いた

f = open("history_export.csv", "r")
line= 5
for x in range(line):
    a = f.readline()
    print(a)

コンテキストマネージャーを使用しないのはなぜですか?いずれにせよ、これが多くの既存の回答をどのように改善するかはわかりません。
AMC


0

fname = input("Enter file name: ")
num_lines = 0

with open(fname, 'r') as f: #lines count
    for line in f:
        num_lines += 1

num_lines_input = int (input("Enter line numbers: "))

if num_lines_input <= num_lines:
    f = open(fname, "r")
    for x in range(num_lines_input):
        a = f.readline()
        print(a)

else:
    f = open(fname, "r")
    for x in range(num_lines_input):
        a = f.readline()
        print(a)
        print("Don't have", num_lines_input, " lines print as much as you can")


print("Total lines in the text",num_lines)

-1
#!/usr/bin/python

import subprocess

p = subprocess.Popen(["tail", "-n 3", "passlist"], stdout=subprocess.PIPE)

output, err = p.communicate()

print  output

この方法は私のために働いた


ただし、これは実際にはPythonソリューションではありません。
AMC

私はあなたの答えに何が書かれているのかさえわかりません。説明を追加してください。
アレクセイマリニチェンコ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.