จะเขียนอาร์เรย์หลายมิติไปยังไฟล์ข้อความได้อย่างไร?


116

ในคำถามอื่นผู้ใช้รายอื่นเสนอความช่วยเหลือหากฉันสามารถจัดหาอาร์เรย์ที่ฉันประสบปัญหาได้ อย่างไรก็ตามฉันยังล้มเหลวในงาน I / O พื้นฐานเช่นการเขียนอาร์เรย์ไปยังไฟล์

ใครช่วยอธิบายได้ไหมว่าฉันจะต้องเขียนอาร์เรย์ numpy ขนาด 4x11x14 ลงในไฟล์

อาร์เรย์นี้ประกอบด้วยอาร์เรย์ 11 x 14 สี่อาร์เรย์ดังนั้นฉันควรจัดรูปแบบด้วยบรรทัดใหม่ที่ดีเพื่อให้ผู้อื่นอ่านไฟล์ได้ง่ายขึ้น

แก้ไข : ฉันได้ลองใช้ฟังก์ชัน numpy.savetxt แล้ว มันทำให้เกิดข้อผิดพลาดต่อไปนี้:

TypeError: float argument required, not numpy.ndarray

ฉันคิดว่านี่เป็นเพราะฟังก์ชันไม่ทำงานกับอาร์เรย์หลายมิติ? วิธีแก้ปัญหาใด ๆ ตามที่ฉันต้องการภายในไฟล์เดียวหรือไม่

คำตอบ:


198

หากคุณต้องการที่จะเขียนมันไปยังดิสก์เพื่อที่ว่ามันจะง่ายต่อการอ่านกลับมาในฐานะที่เป็นอาร์เรย์ numpy numpy.saveดูเป็น การดองก็ใช้ได้ดีเช่นกัน แต่มีประสิทธิภาพน้อยกว่าสำหรับอาร์เรย์ขนาดใหญ่ (ซึ่งไม่ใช่ของคุณดังนั้นก็ใช้ได้ดีเช่นกัน)

numpy.savetxtหากคุณต้องการที่จะอ่านได้มนุษย์มองเข้าไป

แก้ไข: ดูเหมือนว่าsavetxtจะไม่ใช่ตัวเลือกที่ยอดเยี่ยมสำหรับอาร์เรย์ที่มี> 2 มิติ ... แต่เพียงเพื่อดึงทุกอย่างออกมาให้ได้ข้อสรุปทั้งหมด:

ฉันเพิ่งรู้ว่าnumpy.savetxtchokes บน ndarrays ที่มีมากกว่า 2 มิติ ... นี่อาจเป็นเพราะการออกแบบเนื่องจากไม่มีวิธีกำหนดโดยธรรมชาติในการระบุมิติเพิ่มเติมในไฟล์ข้อความ

เช่นนี้ (อาร์เรย์ 2D) ทำงานได้ดี

import numpy as np
x = np.arange(20).reshape((4,5))
np.savetxt('test.txt', x)

ในขณะที่สิ่งเดียวกันจะล้มเหลว (ด้วยข้อผิดพลาดที่ค่อนข้างไม่เป็นข้อมูล :) TypeError: float argument required, not numpy.ndarrayสำหรับอาร์เรย์ 3 มิติ:

import numpy as np
x = np.arange(200).reshape((4,5,10))
np.savetxt('test.txt', x)

วิธีแก้ปัญหาอย่างหนึ่งคือการแบ่งอาร์เรย์ 3 มิติ (หรือสูงกว่า) ออกเป็นชิ้น 2 มิติ เช่น

x = np.arange(200).reshape((4,5,10))
with file('test.txt', 'w') as outfile:
    for slice_2d in x:
        np.savetxt(outfile, slice_2d)

numpy.loadtxtแต่เป้าหมายของเราคือการเป็นมนุษย์อย่างชัดเจนอ่านได้ในขณะที่ยังคงถูกอ่านได้อย่างง่ายดายกลับไปอยู่กับ ดังนั้นเราสามารถเพิ่มความละเอียดมากขึ้นและแยกความแตกต่างของชิ้นงานโดยใช้บรรทัดที่แสดงความคิดเห็น โดยค่าเริ่มต้นnumpy.loadtxtจะไม่สนใจบรรทัดใด ๆ ที่ขึ้นต้นด้วย#(หรืออักขระใดก็ตามที่ระบุโดยcommentskwarg) (ดูละเอียดกว่าที่เป็นจริง ... )

import numpy as np

# Generate some test data
data = np.arange(200).reshape((4,5,10))

# Write the array to disk
with open('test.txt', 'w') as outfile:
    # I'm writing a header here just for the sake of readability
    # Any line starting with "#" will be ignored by numpy.loadtxt
    outfile.write('# Array shape: {0}\n'.format(data.shape))

    # Iterating through a ndimensional array produces slices along
    # the last axis. This is equivalent to data[i,:,:] in this case
    for data_slice in data:

        # The formatting string indicates that I'm writing out
        # the values in left-justified columns 7 characters in width
        # with 2 decimal places.  
        np.savetxt(outfile, data_slice, fmt='%-7.2f')

        # Writing out a break to indicate different slices...
        outfile.write('# New slice\n')

สิ่งนี้ให้ผล:

# Array shape: (4, 5, 10)
0.00    1.00    2.00    3.00    4.00    5.00    6.00    7.00    8.00    9.00   
10.00   11.00   12.00   13.00   14.00   15.00   16.00   17.00   18.00   19.00  
20.00   21.00   22.00   23.00   24.00   25.00   26.00   27.00   28.00   29.00  
30.00   31.00   32.00   33.00   34.00   35.00   36.00   37.00   38.00   39.00  
40.00   41.00   42.00   43.00   44.00   45.00   46.00   47.00   48.00   49.00  
# New slice
50.00   51.00   52.00   53.00   54.00   55.00   56.00   57.00   58.00   59.00  
60.00   61.00   62.00   63.00   64.00   65.00   66.00   67.00   68.00   69.00  
70.00   71.00   72.00   73.00   74.00   75.00   76.00   77.00   78.00   79.00  
80.00   81.00   82.00   83.00   84.00   85.00   86.00   87.00   88.00   89.00  
90.00   91.00   92.00   93.00   94.00   95.00   96.00   97.00   98.00   99.00  
# New slice
100.00  101.00  102.00  103.00  104.00  105.00  106.00  107.00  108.00  109.00 
110.00  111.00  112.00  113.00  114.00  115.00  116.00  117.00  118.00  119.00 
120.00  121.00  122.00  123.00  124.00  125.00  126.00  127.00  128.00  129.00 
130.00  131.00  132.00  133.00  134.00  135.00  136.00  137.00  138.00  139.00 
140.00  141.00  142.00  143.00  144.00  145.00  146.00  147.00  148.00  149.00 
# New slice
150.00  151.00  152.00  153.00  154.00  155.00  156.00  157.00  158.00  159.00 
160.00  161.00  162.00  163.00  164.00  165.00  166.00  167.00  168.00  169.00 
170.00  171.00  172.00  173.00  174.00  175.00  176.00  177.00  178.00  179.00 
180.00  181.00  182.00  183.00  184.00  185.00  186.00  187.00  188.00  189.00 
190.00  191.00  192.00  193.00  194.00  195.00  196.00  197.00  198.00  199.00 
# New slice

การอ่านย้อนกลับเป็นเรื่องง่ายมากตราบใดที่เรารู้รูปร่างของอาร์เรย์เดิม numpy.loadtxt('test.txt').reshape((4,5,10))เราก็สามารถทำได้ เป็นตัวอย่าง (คุณสามารถทำได้ในบรรทัดเดียวฉันแค่อธิบายสิ่งต่าง ๆ อย่างละเอียด):

# Read the array from disk
new_data = np.loadtxt('test.txt')

# Note that this returned a 2D array!
print new_data.shape

# However, going back to 3D is easy if we know the 
# original shape of the array
new_data = new_data.reshape((4,5,10))

# Just to check that they're the same...
assert np.all(new_data == data)

2
+1 จากฉันโปรดดูด้วยnumpy.loadtxt( docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html )
Dominic Rodger

2
ตอนนี้มีวิธีแก้ปัญหาที่ง่ายกว่ามาก: yourStrArray = np.array ([str (val) สำหรับ val ใน yourMulDArray], dtype = 'string'); np.savetxt ('YourTextFile.txt', yourStrArray, fmt = '% s')
Greg Kramida

@GregKramida และคุณจะกู้คืนอาร์เรย์ได้อย่างไร?
astrojuanlu

@ Juanlu001: ฉันรู้ว่า numpy.loadtxt (... ) ยังยอมรับอาร์กิวเมนต์ dtype ซึ่งสามารถตั้งค่าเป็น np.string_ ฉันจะให้ช็อตแรกและแบบฟอร์ม นอกจากนี้ยังมี numpy.fromstring (... ) สำหรับการแยกอาร์เรย์จากสตริง
Greg Kramida

เฮ้ถ้าฉันต้องการจัดเก็บอาร์เรย์รูปภาพล่ะ เราจะปรับขนาดได้อย่างไรถ้าขนาดภาพเป็น 512 x 512?
Ambika Saxena

31

ฉันไม่แน่ใจว่าสิ่งนี้ตรงตามความต้องการของคุณหรือไม่เนื่องจากฉันคิดว่าคุณสนใจที่จะทำให้ไฟล์สามารถอ่านได้โดยผู้คน แต่ถ้านั่นไม่ใช่ประเด็นหลักก็แค่pickleนั้น

ในการบันทึก:

import pickle

my_data = {'a': [1, 2.0, 3, 4+6j],
           'b': ('string', u'Unicode string'),
           'c': None}
output = open('data.pkl', 'wb')
pickle.dump(my_data, output)
output.close()

หากต้องการอ่านย้อนกลับ:

import pprint, pickle

pkl_file = open('data.pkl', 'rb')

data1 = pickle.load(pkl_file)
pprint.pprint(data1)

pkl_file.close()

คุณอาจไม่จำเป็นต้องpprintพิมพ์พจนานุกรม
zyy

11

หากคุณไม่ต้องการเอาต์พุตที่มนุษย์อ่านได้อีกทางเลือกหนึ่งที่คุณสามารถลองทำได้คือบันทึกอาร์เรย์เป็น.matไฟล์MATLAB ซึ่งเป็นอาร์เรย์ที่มีโครงสร้าง ฉันดูถูก MATLAB แต่การที่ฉันอ่านและเขียนได้.matในไม่กี่บรรทัดนั้นสะดวกมาก

ซึ่งแตกต่างจากคำตอบของ Joe Kington ข้อดีของสิ่งนี้คือคุณไม่จำเป็นต้องรู้รูปร่างดั้งเดิมของข้อมูลใน.matไฟล์กล่าวคือไม่จำเป็นต้องปรับรูปร่างใหม่เมื่ออ่านเข้าและไม่เหมือนกับการใช้picklea.matไฟล์สามารถอ่านได้โดย MATLAB, และอาจมีโปรแกรม / ภาษาอื่น ๆ ด้วย

นี่คือตัวอย่าง:

import numpy as np
import scipy.io

# Some test data
x = np.arange(200).reshape((4,5,10))

# Specify the filename of the .mat file
matfile = 'test_mat.mat'

# Write the array to the mat file. For this to work, the array must be the value
# corresponding to a key name of your choice in a dictionary
scipy.io.savemat(matfile, mdict={'out': x}, oned_as='row')

# For the above line, I specified the kwarg oned_as since python (2.7 with 
# numpy 1.6.1) throws a FutureWarning.  Here, this isn't really necessary 
# since oned_as is a kwarg for dealing with 1-D arrays.

# Now load in the data from the .mat that was just saved
matdata = scipy.io.loadmat(matfile)

# And just to check if the data is the same:
assert np.all(x == matdata['out'])

หากคุณลืมคีย์ที่ตั้งชื่ออาร์เรย์ไว้ใน.matไฟล์คุณสามารถทำได้เสมอ:

print matdata.keys()

และแน่นอนคุณสามารถจัดเก็บอาร์เรย์จำนวนมากโดยใช้คีย์อื่น ๆ อีกมากมาย

ใช่ - มันไม่สามารถอ่านได้ด้วยตาของคุณ แต่ใช้เวลาเพียง 2 บรรทัดในการเขียนและอ่านข้อมูลซึ่งฉันคิดว่าเป็นการแลกเปลี่ยนที่ยุติธรรม

ดูเอกสารสำหรับscipy.io.savemat และscipy.io.loadmat และหน้าบทช่วยสอนนี้: scipy.io File IO Tutorial


9

ndarray.tofile() ควรทำงานด้วย

เช่นถ้าอาร์เรย์ของคุณถูกเรียกa:

a.tofile('yourfile.txt',sep=" ",format="%s")

ไม่แน่ใจว่าจะรับการจัดรูปแบบขึ้นบรรทัดใหม่ได้อย่างไร

แก้ไข (เครดิตความคิดเห็นของ Kevin J.Black ที่นี่ ):

ตั้งแต่เวอร์ชัน 1.5.0 np.tofile()ใช้พารามิเตอร์ที่เป็นทางเลือก newline='\n'เพื่ออนุญาตเอาต์พุตหลายบรรทัด https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html


แต่มีวิธีสร้างอาร์เรย์ดั้งเดิมจาก texfile หรือไม่?
Ahashan Alam Sojib


1
tofilenewline='\n'ไม่ได้มี
Nico Schlömer


1

คุณสามารถสำรวจอาร์เรย์ในสามลูปที่ซ้อนกันและเขียนค่าลงในไฟล์ของคุณ สำหรับการอ่านคุณเพียงแค่ใช้โครงสร้างลูปเดียวกัน คุณจะได้รับค่าตามลำดับที่ถูกต้องเพื่อเติมอาร์เรย์ของคุณให้ถูกต้องอีกครั้ง


0

ฉันมีวิธีทำได้โดยใช้การดำเนินการเพียงแค่ filename.write () มันใช้งานได้ดีสำหรับฉัน แต่ฉันกำลังจัดการกับอาร์เรย์ที่มีองค์ประกอบข้อมูล ~ 1500

โดยพื้นฐานแล้วฉันแค่มีลูปเพื่อวนซ้ำผ่านไฟล์และเขียนไปยังเอาต์พุตปลายทางทีละบรรทัดในเอาต์พุตสไตล์ csv

import numpy as np

trial = np.genfromtxt("/extension/file.txt", dtype = str, delimiter = ",")

with open("/extension/file.txt", "w") as f:
    for x in xrange(len(trial[:,1])):
        for y in range(num_of_columns):
            if y < num_of_columns-2:
                f.write(trial[x][y] + ",")
            elif y == num_of_columns-1:
                f.write(trial[x][y])
        f.write("\n")

คำสั่ง if และ elif ใช้เพื่อเพิ่มลูกน้ำระหว่างองค์ประกอบข้อมูล ไม่ว่าด้วยเหตุผลใดสิ่งเหล่านี้จะถูกตัดออกเมื่ออ่านไฟล์ในรูปแบบอาร์เรย์ nd เป้าหมายของฉันคือการส่งออกไฟล์เป็น csv ดังนั้นวิธีนี้จึงช่วยจัดการได้

หวังว่านี่จะช่วยได้!


0

Pickle เหมาะที่สุดสำหรับกรณีเหล่านี้ สมมติว่าคุณมี ndarray x_trainที่ชื่อว่า คุณสามารถถ่ายโอนข้อมูลลงในไฟล์และเปลี่ยนกลับโดยใช้คำสั่งต่อไปนี้:

import pickle

###Load into file
with open("myfile.pkl","wb") as f:
    pickle.dump(x_train,f)

###Extract from file
with open("myfile.pkl","rb") as f:
    x_temp = pickle.load(f)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.