Как перевести строковые значения Decimal в число?
Есть текстовый файл с данными такого вида:
-7.271467826427747 17.84
-7.238717596285217 17.83
-7.203784017466519 17.82
-7.171033787323988 17.81
-7.138283557181459 17.80
-7.103349978362760 17.79
-7.068416399544062 17.78
-7.033482820725363 17.77
-6.998549241906665 17.76
-6.961432314411798 17.75
-6.924315386916930 17.74
-6.889381808098232 17.73
-6.852264880603365 17.72
-6.812964604432329 17.71
-6.775847676937462 17.70
-6.738730749442595 17.69
-6.699430473271558 17.68
-6.660130197100525 17.67
-6.618646572253319 17.66
-6.577162947406114 17.65
-6.537862671235079 17.64
-6.496379046387874 17.63
-6.452712072864502 17.62
-6.409045099341129 17.61
-6.365378125817755 17.60
Я пытаюсь перегнать этот файл в массив:
import numpy as np
_overall_survival = open('_overall_survival.txt').read().splitlines()
mas = np.array([line.split() for line in _overall_survival[0:]], float, order='F')
print(mas)
На выходе получаем:
[[-39.16145859 81.01 ]
[-39.81064093 81.02 ]
[-40.02431799 81.03 ]
...
[ -2.39123878 17.24 ]
[ -2.45739627 17.23 ]
[ -2.5248678 17.22 ]]
В принципе работает, но, float не обеспечивает точности передачи знаков после запятой, а это важно.
Я попробовал использовать Decimal:
from decimal import *
import numpy as np
_overall_survival = open('_overall_survival.txt').read().splitlines()
mas = np.array([line.split() for line in _overall_survival[0:]], Decimal, order='F')
print(mas)
На выходе получаем:
[['-39.161458590547106' '81.01']
['-39.810640930261251' '81.02']
['-40.024317987368960' '81.03']
...
['-2.391238778978993' '17.24']
['-2.457396265486048' '17.23']
['-2.524867804437093' '17.22']]
В этом случае массив отображается со всеми знаками после запятой, но, это строковые данные и их нужно еще как-то перегнать в числовые данные.
Вопрос: как сохраняя точность Decimal, получить не строку, а число?
ДОПОЛНЕНИЕ:
Опираясь на советы Stanislav Volodarskiy, CrazyElf, Vitalizzare удалось собрать работоспособный прототип программы.
import tkinter as tk
import numpy as np
from tkinter import ttk
with open('_overall_survival.txt') as f:
array = np.array([list(map(float, line.split())) for line in f])
with ((np.printoptions(precision=15))):
mas = array
# ENGINE
# region
def calc():
with ((np.printoptions(precision=15))):
result = float((-0.02144927 * float(entry_a.get())
) + (-0.04948455 * float(entry_b.get())
) + 0.50824824)
row = mas[np.abs(mas[:, 0] - result).argmin()]
min_row = float(mas[np.abs(mas[:, 0]).argmin()][0])
max_row = float(mas[np.abs(mas[:, 0]).argmax()][0])
if min_row >= result >= max_row:
score['text'] = mas[np.where(mas == row)][1]
info['text'] = (f'Расчет: {result}\n'
f'ТОЧНОГО СОВПАДЕНИЯ НЕТ!\n'
f'Ближайшее значение: '
f'{mas[np.where(mas == row)][0]}\n'
f'Связанное значение: '
f'{mas[np.where(mas == row)][1]}')
elif result < max_row:
score['text'] = mas[np.where(mas == row)][1]
info['text'] = (f'Расчет: {result}\n'
f'СОВПАДЕНИЙ НЕТ!\n'
f'Расчетное время больше: '
f'{mas[np.where(mas == row)][1]}')
elif result > max_row:
score['text'] = mas[np.where(mas == row)][1]
info['text'] = (f'Расчет: {result}\n'
f'СОВПАДЕНИЙ НЕТ!\n'
f'Расчетное время меньше: '
f'{mas[np.where(mas == row)][1]}')
elif result in mas[:, 0]:
score['text'] = mas[np.where(mas == row)][1]
info['text'] = (f'Расчет: {result}\n'
f'ЕСТЬ СОВПАДЕНИЕ!\n'
f'Связанное значение: '
f'{mas[np.where(mas == row)][1]}')
def clear():
entry_a.delete(0, 'end')
entry_b.delete(0, 'end')
# combobox.set('')
score['text'] = ''
# endregion
# WINDOW
# region
app = tk.Tk()
app.title('FRM CLEAR')
width = 600
height = 350
x = int((app.winfo_screenwidth() / 2) - (width / 2))
y = int((app.winfo_screenheight() / 2) - (height / 2))
app.geometry(f'{width}x{height}+{x}+{y}')
app.resizable(width=False, height=False)
app['background'] = '#3d505a'
# endregion
# RESOURCES
# region
ttk.Style().configure('btn.TButton', background='#56676f')
ttk.Style().configure('frm_app.TFrame', background='#3d505a')
ttk.Style().configure('frm_content.TFrame', background='#56676f')
frm_app = ttk.Frame(app, style='frm_app.TFrame', padding=[20, 20])
frm_app.place(relheight=1, relwidth=1)
frm_content = ttk.Frame(frm_app, style='frm_content.TFrame', padding=[10, 10])
frm_content.place(relheight=0.5, relwidth=1)
# endregion
# UI
# region
entry_a = ttk.Entry(frm_content)
entry_a.place(x=5, y=10, height=25, width=40)
entry_b = ttk.Entry(frm_content)
entry_b.place(x=5, y=45, height=25, width=40)
score = ttk.Label(frm_content, text='', font='Tahoma 20 bold')
score.place(x=235, y=10, height=38, width=300)
info = ttk.Label(frm_content, text='', font='Tahoma 12',
foreground='#ffffff', background='#56676f')
info.place(x=235, y=50, height=77, width=300)
tk.Button(app, text="Calc", command=calc
).place(x=470, y=305, height=25, width=50)
tk.Button(app, text="Clear", command=clear
).place(x=530, y=305, height=25, width=50)
# endregion
app.mainloop()
Насчет поэкспериментировать с Decimal, я сделаю такой вариант, но, поскольку в дальнейшем там происходят не столько вычисления, сколько поиск и сравнение с содержимым массива, разницы не будет (ну или она не будет влиять на результат сравнения).
Ответы (1 шт):
NumPy не печатает все значащие цифры, его надо настроить: numpy.set_printoptions.
import numpy as np
with open('temp.txt') as f:
a = np.array([
list(map(float, line.split()))
for line in f
])
with np.printoptions(precision=15):
print(a)
Все цифры на месте:
$ python np-print.py [[-7.271467826427747 17.84 ] [-7.238717596285217 17.83 ] [-7.203784017466519 17.82 ] [-7.171033787323988 17.81 ] [-7.138283557181459 17.8 ]]
Если всё-таки хотите работать с decimal.Decimal, то NumPy может ими манипулировать. Медленно, но может:
import decimal
import numpy as np
with open('temp.txt') as f:
a = np.array([
list(map(decimal.Decimal, line.split()))
for line in f
])
print(a)
print(2 * a)
$ python np-decimal.py [[Decimal('-7.271467826427747') Decimal('17.84')] [Decimal('-7.238717596285217') Decimal('17.83')] [Decimal('-7.203784017466519') Decimal('17.82')] [Decimal('-7.171033787323988') Decimal('17.81')] [Decimal('-7.138283557181459') Decimal('17.80')]] [[Decimal('-14.542935652855494') Decimal('35.68')] [Decimal('-14.477435192570434') Decimal('35.66')] [Decimal('-14.407568034933038') Decimal('35.64')] [Decimal('-14.342067574647976') Decimal('35.62')] [Decimal('-14.276567114362918') Decimal('35.60')]]