Избегайте научной нотации для функции scipy io.mmwrite

#python #file-io #scipy #format #sparse-matrix

#python #file-io #scipy #формат #разреженная матрица

Вопрос:

Я пытаюсь экспортировать разреженную матрицу типа ‘<class ‘numpy.float32’>, хранящуюся в формате csr, используя from scipy: io.mmwrite , которая хорошо справляется с разреженностью данных. Однако этот вывод представлен в научной нотации:

 %%MatrixMarket matrix coordinate real general
%
1719 2504 4304376
1 1 -9.0979224e-01
2 1 -1.6585451e-01
  

и я хотел бы получить его в виде обычного числа с плавающей запятой для сценария последующей обработки, который ожидает классические значения с плавающей запятой в формате mtx.

Есть ли способ легко добиться этого?

Мое текущее решение заключалось в повторном чтении записанного файла mtx и преобразовании для всех строк 3-го поля, что не экономит время…

Есть ли способ указать scipy нотацию для использования? Что-то вроде :

np.set_printoptions(suppress=True)

Я также попытался принудительно преобразовать в double / float и не смог найти связанную тему.

Спасибо

Ответ №1:

Вот быстрый хак, который может сработать для вас. (Это хак, потому что он переопределяет частный статический метод класса, который на самом деле не документирован как часть общедоступного API. Если базовый код будет изменен в будущей версии SciPy, этот хак может больше не работать.)

Создайте подкласс scipy.io.mmfile.MMFile , который переопределяет _field_template метод, чтобы он возвращал настраиваемую строку формата. Например.

 from scipy.io.mmio import MMFile


class MMFileFixedFormat(MMFile):

    def _field_template(self, field, precision):
        # Override MMFile._field_template.
        return f'%.{precision}fn'
  

Чтобы написать файл matrix market с этим классом, замените использование функции scipy.io.mmwrite на MMFileFixedFormat().write .

Вот пример в сеансе ipython. Введена разреженная матрица a .

 In [77]: a
Out[77]: 
<5x5 sparse matrix of type '<class 'numpy.float32'>'
    with 8 stored elements in Compressed Sparse Row format>

In [78]: a.A
Out[78]: 
array([[0.27621606, 0.        , 0.        , 0.7780487 , 0.        ],
       [0.7295764 , 0.        , 0.        , 0.        , 0.        ],
       [0.09457383, 0.        , 0.13346413, 0.        , 0.        ],
       [0.        , 0.        , 0.11267778, 0.        , 0.        ],
       [0.05113978, 0.        , 0.        , 0.9891698 , 0.        ]],
      dtype=float32)
  

Вот строка, которая записывает a в файл "a.mtx" .

 In [79]: MMFileFixedFormat().write('a.mtx', a, precision=9)                                                         
  

Взгляните на файл:

 In [80]: !cat a.mtx                                                                                                 
%%MatrixMarket matrix coordinate real general
%
5 5 8
1 1 0.27621606
1 4 0.77804869
2 1 0.72957641
3 1 0.09457383
3 3 0.13346413
4 3 0.11267778
5 1 0.05113978
5 4 0.98916978
  

Возможно, вы захотите настроить строку формата, которая создается в функции _field_template() . Потенциальная проблема с форматом с фиксированным количеством знаков после запятой заключается в том, что если запись имеет значение 0.00000098765432 , она будет напечатана как 0.000000099 , и 0.0000000000123 будет напечатана как 0.00000000 (при условии, что вы использовали то precision же самое, что и в примере выше).


Обратите внимание, однако, что правильное средство чтения файла matrix market должно уметь обрабатывать числа, записанные в научной нотации.