Большой участок: ~20 миллионов образцов, гигабайт данных
У меня есть проблема (с моей ОЗУ) здесь: он не в состоянии держать данные, которые я хочу построить. У меня достаточно места для HD. Есть ли какое-либо решение, чтобы избежать этого "затенения" моего набора данных?
конкретно я имею дело с цифровой обработкой сигнала, и я должен использовать высокую частоту дискретизации. Мой фреймворк (GNU Radio) сохраняет значения (чтобы не использовать слишком много места на диске) в двоичном формате. Я распаковываю его. После этого мне нужно построить заговор. Мне нужен сюжет масштабируемый и интерактивный. И это проблема.
есть ли потенциал оптимизации для этого или другого программного обеспечения / языка программирования (например, R или так), который может обрабатывать большие наборы данных? На самом деле я хочу гораздо больше данных в мои планы. Но у меня нет опыта работы с другими программами. GNUplot терпит неудачу, с аналогичным подходом к следующему. Я не знаю R (jet).
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import struct
"""
plots a cfile
cfile - IEEE single-precision (4-byte) floats, IQ pairs, binary
txt - index,in-phase,quadrature in plaintext
note: directly plotting with numpy results into shadowed functions
"""
# unpacking the cfile dataset
def unpack_set(input_filename, output_filename):
index = 0 # index of the samples
output_filename = open(output_filename, 'wb')
with open(input_filename, "rb") as f:
byte = f.read(4) # read 1. column of the vector
while byte != "":
# stored Bit Values
floati = struct.unpack('f', byte) # write value of 1. column to a variable
byte = f.read(4) # read 2. column of the vector
floatq = struct.unpack('f', byte) # write value of 2. column to a variable
byte = f.read(4) # next row of the vector and read 1. column
# delimeter format for matplotlib
lines = ["%d," % index, format(floati), ",", format(floatq), "n"]
output_filename.writelines(lines)
index = index + 1
output_filename.close
return output_filename.name
# reformats output (precision configuration here)
def format(value):
return "%.8f" % value
# start
def main():
# specify path
unpacked_file = unpack_set("test01.cfile", "test01.txt")
# pass file reference to matplotlib
fname = str(unpacked_file)
plt.plotfile(fname, cols=(0,1)) # index vs. in-phase
# optional
# plt.axes([0, 0.5, 0, 100000]) # for 100k samples
plt.grid(True)
plt.title("Signal-Diagram")
plt.xlabel("Sample")
plt.ylabel("In-Phase")
plt.show();
if __name__ == "__main__":
main()
что-то вроде plt.swap_on_disk () может кэшировать материал на моем SSD;)
5 ответов:
таким образом, ваши данные не так уж велики, и тот факт, что у вас возникли проблемы с его построением, указывает на проблемы с инструментами. Matplotlib.... разве это не хорошо. У него есть много вариантов, и выход в порядке, но это огромная память, и она принципиально предполагает, что ваши данные малы. Но есть и другие варианты.
Итак, в качестве примера, я сгенерировал файл 20M data-point ' bigdata.Бинь, используя следующие кнопки:
#!/usr/bin/env python import numpy import scipy.io.numpyio npts=20000000 filename='bigdata.bin' def main(): data = (numpy.random.uniform(0,1,(npts,3))).astype(numpy.float32) data[:,2] = 0.1*data[:,2]+numpy.exp(-((data[:,1]-0.5)**2.)/(0.25**2)) fd = open(filename,'wb') scipy.io.numpyio.fwrite(fd,data.size,data) fd.close() if __name__ == "__main__": main()
это создает файл размером ~229 МБ, который это не так уж и много; но вы выразили, что хотели бы перейти к еще большим файлам, поэтому в конечном итоге вы попадете в пределы памяти.
давайте сначала сосредоточимся на неинтерактивных сюжетах. Первое, что нужно понять, это то, что векторные графики с глифами в каждой точке будут катастрофой - для каждой из 20 м точек, большинство из которых все равно будут перекрываться, пытаясь отобразить маленькие кресты или круги или что-то будет диастером, генерируя огромные файлы и принимая тонны время. Это, я думаю, то, что тонет matplotlib по умолчанию.
Gnuplot не имеет никаких проблем с этим:
gnuplot> set term png gnuplot> set output 'foo.png' gnuplot> plot 'bigdata.bin' binary format="%3float32" using 2:3 with dots
и даже Matplotlib можно заставить вести себя с некоторой осторожностью (выбирая растровый задний конец и используя пиксели для обозначения точек):
#!/usr/bin/env python import numpy import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt datatype=[('index',numpy.float32), ('floati',numpy.float32), ('floatq',numpy.float32)] filename='bigdata.bin' def main(): data = numpy.memmap(filename, datatype, 'r') plt.plot(data['floati'],data['floatq'],'r,') plt.grid(True) plt.title("Signal-Diagram") plt.xlabel("Sample") plt.ylabel("In-Phase") plt.savefig('foo2.png') if __name__ == "__main__": main()
Теперь, если вы хотите интерактивную, вам придется бин данные для построения графика, и увеличить на лету. Я не знаю никаких инструментов python, которые поможет вам сделать это навскидку.
С другой стороны, построение больших данных-довольно распространенная задача, и есть инструменты, которые подходят для этой работы. Paraview мой личный фаворит, и посетить еще один. Они оба в основном предназначены для 3D-данных, но Paraview, в частности, также делает 2d и очень интерактивен (и даже имеет интерфейс сценариев Python). Единственный трюк будет заключаться в том, чтобы записать данные в формат файла, который Paraview может легко читать.
вы можете, конечно, оптимизировать чтение вашего файла: вы можете напрямую прочитать его в массив NumPy, чтобы использовать необработанную скорость NumPy. У вас есть несколько вариантов. Если ОЗУ является проблемой, вы можете использовать memmap, который держит большую часть файла на диске (а не в оперативной памяти):
# Each data point is a sequence of three 32-bit floats: data = np.memmap(filename, mode='r', dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])
Если ОЗУ не является проблемой, вы можете поместить весь массив в ОЗУ с fromfile:
data = np.fromfile(filename, dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])
построение графика может быть сделано с обычным Matplotlib
plot(*data)
функция, возможно, через метод "увеличения", предложенный в другом решении.
более поздний проект имеет большой потенциал для больших наборов данных:размытие, который был создан с именно это в виду.
на самом деле, только данные, которые имеют отношение к масштабу графика, отправляются на бэкэнд дисплея. Этот подход намного быстрее, чем подход Matplotlib.
Я бы предложил что-то немного сложное, но это должно работать : построить свой график в разных разрешениях, для разных диапазонов.
подумайте о Google Earth, например. Если вы unzoom на максимальном уровне, чтобы охватить всю планету, разрешение является самым низким. При увеличении изображения меняются на более подробные, но только в том регионе, на который вы увеличиваете масштаб.
Так что в основном для вашего сюжета (это 2D ? 3D ? Я предполагаю, что это 2D), я предлагаю вам построить один большой график это охватывает весь диапазон [0, n] с низким разрешением, 2 меньших графика, которые охватывают [0, n/2] и [n/2 + 1, n] с удвоенным разрешением большого, 4 меньших графика, которые охватывают [0, n/4] ... [3 * n / 4 + 1, n] с удвоенным разрешением 2 выше, и так далее.
Не уверен, что мое объяснение очень ясно. Кроме того, я не знаю, обрабатывается ли такой график с несколькими разрешениями любой существующей программой построения.
интересно, есть ли выигрыш, чтобы ускорить поиск ваших очков? (Я был заинтригован r* (r star) деревья на некоторое время.)
интересно, если использовать что-то вроде дерева r* в этом случае может быть путь. (при уменьшении масштаба более высокие узлы в дереве могут содержать информацию о более грубом, уменьшенном рендеринге, узлы дальше к листьям содержат отдельные образцы)
может быть, даже карта памяти дерева (или любой структуры вы в конечном итоге использование) в память, чтобы сохранить производительность и низкое использование ОЗУ. (вы разгружаете задачу управления памятью в ядро)
надеюсь, что это имеет смысл.. немного бессвязно. уже поздно!