Bir metin dosyasına çok boyutlu bir dizi nasıl yazılır?


116

Başka bir soruda, sorun yaşadığım diziyi tedarik edebilirsem, diğer kullanıcılar biraz yardım teklif etti. Bununla birlikte, bir dosyaya bir dizi yazmak gibi temel bir G / Ç görevinde bile başarısız oluyorum.

Dosyaya bir 4x11x14 numpy dizisi yazmak için ne tür bir döngüye ihtiyacım olduğunu açıklayabilir mi?

Bu dizi dört adet 11 x 14 diziden oluşuyor, bu yüzden dosyanın okunmasını diğerlerinde kolaylaştırmak için güzel bir satırsonu ile biçimlendirmeliyim.

Düzenleme : Bu yüzden numpy.savetxt işlevini denedim. Garip bir şekilde şu hatayı veriyor:

TypeError: float argument required, not numpy.ndarray

Bunun, işlevin çok boyutlu dizilerle çalışmamasından kaynaklandığını varsayıyorum. Tek bir dosyada istediğim herhangi bir çözüm var mı?

Yanıtlar:


198

Eğer onu diske yazmak istiyorsanız, böylece bir numpy dizisi olarak tekrar okunmasının kolay olmasını istiyorsanız, içine bakın numpy.save. Turşu yapmak da iyi çalışır, ancak büyük diziler için daha az etkilidir (sizinki değildir, bu yüzden de mükemmeldir).

İnsan tarafından okunabilir olmasını istiyorsanız, içine bakın numpy.savetxt.

Düzenleme: Yani, savetxt2 boyutlu diziler için pek de iyi bir seçenek değil gibi görünüyor ... Ama sadece her şeyi tam sonuca çıkarmak için:

numpy.savetxt2'den fazla boyuta sahip ndarray'larda tıkanmalar olduğunu yeni fark ettim ... Bu muhtemelen tasarım gereğidir, çünkü bir metin dosyasında ek boyutları belirtmenin doğası gereği tanımlanmış bir yolu yoktur.

Örneğin, Bu (bir 2D dizisi) iyi çalışıyor

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

Aynı şey TypeError: float argument required, not numpy.ndarraybir 3B dizi için başarısız olsa da (oldukça bilgilendirici olmayan bir hatayla :) :

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

Çözümlerden biri, yalnızca 3B (veya daha büyük) diziyi 2B dilimlere bölmektir. Örneğin

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)

Bununla birlikte, amacımız açıkça okunabilir ve yine de kolayca okunabilir olmaktır numpy.loadtxt. Bu nedenle, biraz daha ayrıntılı olabilir ve dilimleri yorumlanmış satırları kullanarak ayırt edebiliriz. Varsayılan olarak, numpy.loadtxtile başlayan #(veya commentskwarg tarafından hangi karakter belirtilmişse ) tüm satırları yok sayacaktır . (Bu gerçekte olduğundan daha ayrıntılı görünüyor ...)

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')

Bu, şunları verir:

# 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

Orijinal dizinin şeklini bildiğimiz sürece onu tekrar okumak çok kolaydır. Sadece yapabiliriz numpy.loadtxt('test.txt').reshape((4,5,10)). Örnek olarak (Bunu bir satırda yapabilirsiniz, ben sadece açıklığa kavuşturmak için ayrıntılı söylüyorum):

# 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
Bu sorunun şimdi çok daha kolay bir çözümü var: yourStrArray = np.array ([str (val) yourMulDArray içindeki val için], dtype = 'string'); np.savetxt ('YourTextFile.txt', yourStrArray, fmt = '% s')
Greg Kramida

@GregKramida ve diziyi nasıl kurtarırsınız?
astrojuanlu

@ Juanlu001: numpy.loadtxt (...) 'nin np.string_ olarak ayarlanabilen bir dtype argümanını da kabul ettiğini biliyorum. Buna bir şans verirdim, her şeyden önce. Dizileri dizelerden ayrıştırmak için bir numpy.fromstring (...) de vardır.
Greg Kramida

Hey, bir görüntü dizisini saklamam gerekirse? Resim boyutu 512 x 512 olsaydı nasıl yeniden boyutlandırırdık?
Ambika Saxena

31

Dosyayı insanlar tarafından okunabilir hale getirmekle ilgilendiğinizi düşündüğüm için bunun gereksinimlerinizi karşılayıp karşılamadığından emin değilim, ancak bu birincil bir endişe değilse, sadece picklebu.

Kaydetmek için:

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()

Tekrar okumak için:

import pprint, pickle

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

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

pkl_file.close()

pprintSözlüğü yazdırmak için ihtiyacınız olmayabilir .
zyy

11

İnsan tarafından okunabilir bir çıktıya ihtiyacınız yoksa, deneyebileceğiniz başka bir seçenek de diziyi .matyapılandırılmış bir dizi olan MATLAB dosyası olarak kaydetmektir . MATLAB'ı küçümsüyorum, ancak .matbirkaç satırda hem okuyup hem de yazabiliyor olmam uygun.

Joe Kington'ın cevabının aksine, bunun yararı , dosyadaki verilerin orijinal şeklini bilmenize gerek olmamasıdır.mat , yani okurken yeniden şekillendirmenize gerek yoktur. Kullanmanın aksine pickle, bir .matdosya MATLAB tarafından okunabilir, ve muhtemelen diğer bazı programlar / diller de.

İşte bir örnek:

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'])

Dizinin .matdosyada adlandırıldığı anahtarı unutursanız, her zaman şunları yapabilirsiniz:

print matdata.keys()

Ve tabii ki çok daha fazla anahtar kullanarak birçok diziyi saklayabilirsiniz.

Yani evet - gözlerinizle okunamayacak, ancak verileri yazmak ve okumak sadece 2 satır alıyor, ki bence bu adil bir takas.

Scipy.io.savemat ve scipy.io.loadmat için dokümanlara ve ayrıca şu eğitim sayfasına bir göz atın : scipy.io Dosya GÇ Eğitimi


9

ndarray.tofile() ayrıca çalışmalı

örneğin, diziniz çağrılırsa a:

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

Yine de yeni satır biçimlendirmesini nasıl alacağınızdan emin değilim.

Düzenleme ( burada Kevin J. Black'in yorumuna atıfta bulunun ):

1.5.0 sürümünden bu yana, çok hatlı çıkışa izin vermek np.tofile()için isteğe bağlı bir parametre alır newline='\n'. https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.savetxt.html


Ancak texfile'dan orijinal dizi oluşturmanın bir yolu var mı?
Ahashan Alam Sojib


1
tofilesahip değil newline='\n'.
Nico Schlömer


1

Diziyi üç iç içe döngüde kolayca gezebilir ve değerlerini dosyanıza yazabilirsiniz. Okumak için, aynı döngü yapısını kullanmanız yeterlidir. Dizilerinizi tekrar doğru şekilde doldurmak için değerleri tam olarak doğru sırada alacaksınız.


0

Bunu basit bir filename.write () işlemi kullanarak yapmanın bir yolu var. Benim için iyi çalışıyor, ancak ~ 1500 veri elemanına sahip dizilerle uğraşıyorum.

Temelde döngülerin dosya boyunca yinelemesi ve csv stili çıktıda çıktı hedefine satır satır yazması için var.

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")

İf ve elif ifadesi, veri öğeleri arasına virgül eklemek için kullanılır. Sebep ne olursa olsun, dosyayı nd dizisi olarak okurken bunlar çıkarılır. Amacım dosyayı bir csv olarak çıkarmaktı, bu yüzden bu yöntem bunun üstesinden gelmeye yardımcı oluyor.

Bu yardımcı olur umarım!


0

Turşu bu durumlar için en iyisidir. Adında bir ndarray olduğunu varsayalım x_train. Aşağıdaki komutu kullanarak bir dosyaya dökebilir ve geri döndürebilirsiniz:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.