2012-05-09 42 views
6

Tôi mới dùng python và đang cố đọc "khối" dữ liệu từ một tệp. Tệp được viết như sau:Đọc các khối dữ liệu từ một tệp trong Python

# Some comment 
# 4 cols of data --x,vx,vy,vz 
# nsp, nskip =   2   10 


#   0 0.0000000 


#   1   4 
0.5056E+03 0.8687E-03 -0.1202E-02 0.4652E-02 
0.3776E+03 0.8687E-03 0.1975E-04 0.9741E-03 
0.2496E+03 0.8687E-03 0.7894E-04 0.8334E-03 
0.1216E+03 0.8687E-03 0.1439E-03 0.6816E-03 


#   2   4 
0.5056E+03 0.8687E-03 -0.1202E-02 0.4652E-02 
0.3776E+03 0.8687E-03 0.1975E-04 0.9741E-03 
0.2496E+03 0.8687E-03 0.7894E-04 0.8334E-03 
0.1216E+03 0.8687E-03 0.1439E-03 0.6816E-03 


#   500 0.99999422 


#   1   4 
0.5057E+03 0.7392E-03 -0.6891E-03 0.4700E-02 
0.3777E+03 0.9129E-03 0.2653E-04 0.9641E-03 
0.2497E+03 0.9131E-03 0.7970E-04 0.8173E-03 
0.1217E+03 0.9131E-03 0.1378E-03 0.6586E-03 

and so on 

Bây giờ tôi muốn có thể chỉ định và đọc chỉ một khối dữ liệu trong số nhiều khối này. Tôi đang sử dụng numpy.loadtxt('filename',comments='#') để đọc dữ liệu nhưng nó tải toàn bộ tệp trong một lần. Tôi đã tìm kiếm trực tuyến và một người nào đó đã tạo ra một bản vá cho thói quen io numpy để xác định các khối đọc nhưng nó không phải là chủ yếu.

Việc chọn khối dữ liệu trong gnuplot dễ dàng hơn nhiều nhưng tôi phải viết thường trình để vẽ các hàm phân phối. Nếu tôi có thể tìm ra các khối đọc cụ thể, nó sẽ dễ dàng hơn trong python. Ngoài ra, tôi đang di chuyển tất cả các mã trực quan hóa của tôi sang python từ IDL và gnuplot, vì vậy sẽ rất tuyệt khi có mọi thứ trong python thay vì có những thứ nằm rải rác xung quanh trong nhiều gói.

Tôi đã nghĩ đến việc gọi gnuplot từ trong python, vẽ một khối tới một bảng và gán đầu ra cho một số mảng trong python. Nhưng tôi vẫn bắt đầu và tôi không thể tìm ra cú pháp để làm điều đó.

Bất kỳ ý tưởng, con trỏ nào để giải quyết vấn đề này sẽ giúp ích rất nhiều.

+0

Vì vậy, bạn muốn người dùng chỉ định, nói một cặp giá trị (i, j) và đọc tất cả các dòng giữa dòng "# ij" và dòng trống tiếp theo? –

+0

Alsmot!Điều chính xác tôi muốn có thể làm là có thể chỉ định i, j trong đó i là khối khởi đầu và j là khối cuối cùng và một khối được xác định bởi các hàng được phân cách bởi hai hoặc nhiều hàng trống. – toylas

Trả lời

6

Một đọc nhanh cơ bản:

>>> def read_blocks(input_file, i, j): 
    empty_lines = 0 
    blocks = [] 
    for line in open(input_file): 
     # Check for empty/commented lines 
     if not line or line.startswith('#'): 
      # If 1st one: new block 
      if empty_lines == 0: 
       blocks.append([]) 
      empty_lines += 1 
     # Non empty line: add line in current(last) block 
     else: 
      empty_lines = 0 
      blocks[-1].append(line) 
    return blocks[i:j + 1] 

>>> for block in read_blocks(s, 1, 2): 
    print '-> block' 
    for line in block: 
     print line 


-> block 
0.5056E+03 0.8687E-03 -0.1202E-02 0.4652E-02 
0.3776E+03 0.8687E-03 0.1975E-04 0.9741E-03 
0.2496E+03 0.8687E-03 0.7894E-04 0.8334E-03 
0.1216E+03 0.8687E-03 0.1439E-03 0.6816E-03 
-> block 
0.5057E+03 0.7392E-03 -0.6891E-03 0.4700E-02 
0.3777E+03 0.9129E-03 0.2653E-04 0.9641E-03 
0.2497E+03 0.9131E-03 0.7970E-04 0.8173E-03 
0.1217E+03 0.9131E-03 0.1378E-03 0.6586E-03 
>>> 

Bây giờ tôi đoán bạn có thể sử dụng NumPy để đọc các dòng ...

+0

Cảm ơn rất nhiều Emmanuel !! Nó làm việc gần như chính xác ra khỏi hộp. Tôi đã cần phải tìm hiểu một vài bit và chăm sóc không gian trong các tập tin của tôi, vv Tôi cũng đã thực hiện đề xuất của Pascal để chia dòng trước khi thêm khối. Bây giờ mã cuối cùng cho tôi một mảng 3D với mỗi khối như là một mặt phẳng trong mảng 3D. Cảm ơn bạn rất nhiều vì đã giúp đỡ! Tôi ước tôi có thể học python nhanh hơn một chút. – toylas

+0

Có cách nào thực hiện thanh lịch hơn trong dòng này không? b = a.split(); b = np.array (b); b = b.astype (phao) – toylas

+0

Cảm ơn bạn đã xác thực! Liên quan đến câu hỏi của bạn, tôi không thấy lý do tại sao 'b = np.array (a.split()). Astype (float)' sẽ không hoạt động. – Emmanuel

1

Mã sau có lẽ sẽ giúp bạn bắt đầu. Bạn có thể sẽ cần mô-đun tái.

Bạn có thể mở tập tin để đọc sử dụng:

f = open("file_name_here") 

Bạn có thể đọc các tập tin một dòng tại một thời điểm bằng cách sử dụng

line = f.readline() 

Để nhảy vào dòng tiếp theo mà bắt đầu với một " # ", bạn có thể sử dụng:

while not line.startswith("#"): 
    line = f.readline() 

Để phân tích dòng giống như" # ij ", bạn có thể sử dụng thông thường sau xpression:

is_match = re.match("#\s+(\d+)\s+(\d+)",line) 
if is_match: 
    i = is_match.group(1) 
    j = is_match.group(2) 

Xem tài liệu cho mô-đun "re" để biết thêm thông tin về điều này.

Để phân tích một khối, bạn có thể sử dụng các bit mã sau đây:

block = [[]] # block[i][j] will contain element i,j in your block 
while not line.isspace(): # read until next blank line 
    block.append(map(float,line.split(" "))) 
    # splits each line at each space and turns all elements to float 
    line = f.readline() 

Sau đó bạn có thể biến khối của bạn thành một mảng NumPy nếu bạn muốn:

block = np.array(block) 

Miễn là bạn đã nhập khẩu numpy như np. Nếu bạn muốn đọc nhiều khối giữa i và j, chỉ cần đặt mã ở trên để đọc một khối vào một hàm và sử dụng nó nhiều lần.

Hy vọng điều này sẽ hữu ích!

+0

Cảm ơn rất nhiều Pascal! Tôi đã lấy ý tưởng tách dòng từ bài viết của bạn và sử dụng nó trong đề nghị của Emmanual. Cuối cùng tôi sẽ thực hiện đề xuất của bạn phân tích cú pháp văn bản từ dòng '#' quá nhưng ngay bây giờ, tôi chỉ cần có được một mã số làm việc và làm cho một số lô trong tuần này! Sigh ... – toylas

Các vấn đề liên quan