Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 27, 2016 01:09:49

angeline
Зарегистрирован: 2016-11-11
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

Доброго времени суток!

Проблема следующая. Нижепредставленный код работает довольно корректно до момента вычисления переменной total. В файле с результатами total отличается как в большую, так и в меньшую сторону от истинного значения суммы. Чем это может быть вызвано?

 import xlrd
import xlwt
import math
from xlutils.copy import copy
book1 = xlrd.open_workbook("d:/results_test2_lo.xls", on_demand=True, formatting_info=True)
calc_fin = copy(book1)
rep_n = book1.sheet_by_index(1)
j = 1
for i in rep_n.col_values(j, 1):
    rep_n = book1.sheet_by_index(j)
    rn = calc_fin.get_sheet(j)
    g = 1
    total = 0
    for c in rep_n.col_values(g, start_rowx=1):
        s = 0
        sum = 0
        v = 1
        for a in rep_n.row_values(v, start_colx=1):
            vek = rep_n.row_values(g)[v]
            if type(vek) == float:
                s += 1
                sum = sum + vek
            else:
                pass
            v += 1
        if s == 0:
            average = "zero!"
        else:
            average = sum / s
        rn.write(g, v, average)
        e = 1
        summa = 0
        for b in rep_n.row_values(e, start_colx=1):
            vek = rep_n.row_values(g)[e]
            if type(vek) == float:
                razn = (vek - average) ** 2
                summa = summa + razn
                total = total + summa
            else:
                razn = '-'
            rn.write(g, v+e, razn)
            e += 1
            
        rn.write(g, v+e, summa)
        if s == 0:
            otklon = 'zero!'
        elif summa == 0:
            otklon = '-'
        else:
            s_s = s * (s - 1)
            kor = summa / s_s
            otklon = math.sqrt(kor)
        rn.write(g, v+e+1, otklon)
        if average == 'zero!' or otklon == 'zero!' or otklon == '-':
            percent = '-'
        elif average == 0:
            percent = 0
        else:
            percent = (otklon / average)*100
        rn.write(g, v+e+2, percent)
        g += 1
    rn.write(g, v+e, total)
    j += 1
calc_fin.save('d:/results_test4_lo.xls')

Офлайн

#2 Ноя. 27, 2016 02:49:21

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

angeline
Чем это может быть вызвано?
Надо провести отладку: надо просто выводить на экран все значения total, делая паузу каждый раз (через time.sleep() или input() ) и следить, когда total становится неправильным. Ну, и не забывать вместе с total выводить и другие переменные, чтобы и их состояние знать в тот момент.

Так сразу и не скажешь, потому что код запутан.

Тут ещё плохой стиль виден
  
for i in rep_n.col_values(j, 1):
    rep_n = book1.sheet_by_index(j)
Нельзя так делать. Если rep_n уже для чего-то используется, то нельзя его использовать ещё для чего-то. Это запутывает код и делает его нечитаемым. (Ты никогда не знаешь, что в этом rep_n, потому что там уже что-то другое может быть.) А в нечитаемом коде легко закрадываются ошибки, которые потом трудно увидеть (из-за запутанности кода).

Вот пример кода, где перекрывается имя
  
>>> n = 3
>>> 
>>> for i in range(n):
...     n = i - 1
...     print(i)
... 
0
1
2
>>> for i in range(n):
...     n = i - 1
...     print(i)
... 
0
>>> for i in range(n):
...     n = i - 1
...     print(i)
... 
>>>
в результате, не очевидно, почему циклы работают по-разному, хотя выглядят одинаково.



Отредактировано py.user.next (Ноя. 27, 2016 03:07:22)

Офлайн

#3 Ноя. 27, 2016 13:18:24

angeline
Зарегистрирован: 2016-11-11
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

py.user.next
надо просто выводить на экран все значения total

Перед тем, как задать вопрос, уже попробовала, сакрального знания не получила ( Подумала, что, возможно, есть что-то еще, что мне (как человеку, занимающемуся питоном 1,5 недели) не видно. Попробую сейчас еще раз на свежую голову…

py.user.next
Тут ещё плохой стиль виден

Да, я знаю, что так делать нельзя, и все же пришлось пойти на сделку с совестью. По сути строка в начале кода “rep_n = book1.sheet_by_index(1)” мне не нужна, и добавлена она только для того, чтобы “успокоить” компилятор, который без неё отказывался входить в цикл по причине “NameError: name ‘rep_n’ is not defined”.
Как на Ваш взгляд возможно обойти эту проблему изящнее?

Офлайн

#4 Ноя. 27, 2016 13:59:00

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

angeline
Подумала, что, возможно, есть что-то еще, что мне (как человеку, занимающемуся питоном 1,5 недели) не видно.
Надо распутать код, в этом и проблема: если не можешь понять, что в переменной на каждом шаге цикла, это из-за запутанности кода, а не из-за сложности задачи. Сложная задача решается простыми, ясными алгоритмами.

angeline
По сути строка в начале кода “rep_n = book1.sheet_by_index(1)” мне не нужна, и добавлена она только для того, чтобы “успокоить” компилятор
Ну, это признак того, что код поплыл (называют это “пахнущий код”, “код с душком”). Не должно быть случайных строк в коде.

angeline
Как на Ваш взгляд возможно обойти эту проблему изящнее?
Вот опиши задачу от и до.
Потом, какие файлы есть изначально.
Потом, какие файлы из этих начальных нужно получить в результате.
Вот, и только потом надо думать, как решать задачу.

Мне неясно, что ты делаешь даже, а то, что это неправильно, видно из всяких таких конструкций (их немало).

Типа вот этой хрени
angeline
  
        if s == 0:
            average = "zero!"
        else:
            average = sum / s
Либо там число должно быть, либо строка, а вот когда-то строка, а когда-то число - это плохой стиль. Можно туда засунуть число, которое не может быть средним арифметическим (отрицательное или ноль обычный).

Так что опиши задачу, пришли файлы входящий/выходящий и тогда можно будет превратить этот код во что-то нормальное (на функциях).



Отредактировано py.user.next (Ноя. 27, 2016 14:00:01)

Офлайн

#5 Ноя. 27, 2016 18:13:29

angeline
Зарегистрирован: 2016-11-11
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

py.user.next
опиши задачу, пришли файлы входящий/выходящий

Хорошо. Изначально у меня есть n файлов типа Data.xls. Файлы содержат название радионуклида, год измерения и, собственно, значение измерения. Данные таблицы не совпадают по размерам, т.е. количество радионуклидов и количество измерений разнится от файла к файлу.
Задача 1. Получить на выходе файл, в котором первая страница будет идентична содержанию входного файла, а остальные страницы в заголовке имеют имя радионуклида и содержат расчеты. Предположим, что имеется i радионуклидов и j лет измерений. Назовем измеряемую величину А. Имя радионуклида, соответствующее имени страницы, обозначим индексом r. Тогда необходимо найти отношение А(i)/А(r)
Решение:
 import xlrd
import xlwt
from xlutils.copy import copy
book = xlrd.open_workbook("d:/Data.xls", on_demand=True, formatting_info=True)
data = book.sheet_by_index(0)
calc = copy(book)
j = 1
for i in data.col_values(j, 1):
    r_name = data.row_values(j)[0]
    sheet = calc.add_sheet('%s' % r_name, cell_overwrite_ok=True)
    r = 1
    for t in data.col_values(r, 1):
        r_name = data.row_values(r)[0]
        sheet.write(r, 0, r_name)
        r = r + 1
    d = 1
    for p in data.row_values(d, 1):
        m = 1
        god1 = data.row_values(0)[d]
        sheet.write(0, d, god1)
        act_r1 = data.row_values(j)[d]
        for k in data.col_values(m, 1):
             if act_r1 == '<NPI':
                vek1 = 'zero!'
                sheet.write(m, d, vek1)
                m += 1
             elif act_r1 == '-':
                 vek1 = '-'
                 sheet.write(m, d, vek1)
                 m += 1
             else:
                act_r1 = float(act_r1)
                act1 = data.row_values(m)[d]
                if act1 == '<NPI':
                #while m <= 45:
                    vek1 = 0
                elif act1 == '-':
                    vek1 = '-'
                else:
                    act1 = float(act1)
                    vek1 = act1 / act_r1
                sheet.write(m, d, vek1)
                #print m, vek1
                #time.sleep(2)
                m += 1
        d = d + 1
    j = j + 1
calc.save('d:/results_111.xls')

Файл, получаемый на выходе , с ним я и работаю в коде, приведенном ранее, т.к. второй код решает вторую задачу, появившуюся позже.

Задача 2:
Для каждого нуклида найти “Rating”. Для этого по каждому нуклиду (по каждой странице):
1) посчитать среднее значение А(i)/А(r)
2) посчитать квадраты разности ^2
3) посчитать сумму квадратов разности (по строке) ∑^2
4) посчитать среднеквадратичное отклонение: sqrt{ (∑^2) / (число измерений * (число измерений - 1))}
5) перевести в проценты среднеквадратичное отклонение: (среднеквадратичное отклонение) / (среднее значение) * 100
6) закончив обработку страницы, посчитать сумму квадратов разности по всем нуклидам (по столбцу): ∑∑^2. Записать это значение в “хвост” колонки с одинарной суммой и присвоить это же значение на первую страницу файла соответствующему нуклиду в добавленную колонку “Rating”
Мое корявенькое решение:
 import xlrd
import xlwt
import math
from xlutils.copy import copy
book1 = xlrd.open_workbook("d:/results_11.xls", on_demand=True, formatting_info=True)
calc_fin = copy(book1)
rep_n = book1.sheet_by_index(1)
j = 1
for i in rep_n.col_values(j, 1):
    rep_n = book1.sheet_by_index(j)
    rn = calc_fin.get_sheet(j)
    g = 1
    total = 0
    for c in rep_n.col_values(g, start_rowx=1):
        s = 0
        sum = 0
        v = 1
        for a in rep_n.row_values(v, start_colx=1):
            vek = rep_n.row_values(g)[v]
            if type(vek) == float:
                s += 1
                sum = sum + vek
            else:
                pass
            v += 1
        if s == 0:
            average = "zero!"
        else:
            average = sum / s
        rn.write(g, v, average)
        rn.write(0, v, 'average A')
        e = 1
        summa = 0
        for b in rep_n.row_values(e, start_colx=1):
            vek = rep_n.row_values(g)[e]
            god = str(rep_n.row_values(0)[e])
            if type(vek) == float:
                razn = (vek - average) ** 2
                summa = summa + razn
                total = total + summa
            else:
                razn = '-'
            rn.write(g, v + e, razn)
            rn.write(0, v + e, 'A(i)/A(r), %s' % god)
            e += 1
        rn.write(g, v + e, summa)
        rn.write(0, v + e, 'Sum A(i)/A(r)')
        if s == 0:
            otklon = 'zero!'
        elif summa == 0:
            otklon = '-'
        else:
            s_s = s * (s - 1)
            kor = summa / s_s
            otklon = math.sqrt(kor)
        rn.write(g, v + e + 1, otklon)
        rn.write(0, v + e + 1, 'Mean square deviation')
        if average == 'zero!' or otklon == 'zero!' or otklon == '-':
            percent = '-'
        elif average == 0:
            percent = 0
        else:
            percent = (otklon / average) * 100
        rn.write(g, v + e + 2, percent)
        rn.write(0, v + e + 2, '%')
        g += 1
    rn.write(g+1, v + e, total)
    rn_1 = calc_fin.get_sheet(0)
    rn_1.write(0, v, 'Rating')
    rn_1.write(j, v, total)
    j += 1
calc_fin.save('d:/results_22.xls')

Получаемый мною файл

Отредактировано angeline (Ноя. 27, 2016 18:51:48)

Офлайн

#6 Ноя. 27, 2016 20:37:54

angeline
Зарегистрирован: 2016-11-11
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

Спасибо. Основной вопрос темы снялся. Проблема сумматора оказалась элементарной, я не то суммировала

Офлайн

#7 Ноя. 28, 2016 05:10:05

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

angeline
  
        if s == 0:
            otklon = 'zero!'
        elif summa == 0:
            otklon = '-'
        else:
Вот там в файлах вместо “-” должна быть пустота, просто пустота. В питоне - это None. А вместо “zero!” должен быть ноль обычный.

Но это всё мелочи, конечно. Я вот не понял, почему у тебя на листе с названием радионуклида перечислены все остальные радионуклиды. По идее, у тебя там должны быть листы, равные входным файлам. А каждый входной файл содержит измерения по нескольким радионуклидам за несколько лет. А потом уже, когда эти файлы будут выровнены, можно уже вести подсчёты. То есть между первым (Data.xls) и вторым (result_111.xls) файлом не хватает ещё одного, промежуточного файла, пригодного для вычислений. Иначе ты просто смешиваешь выравнивание таблиц и вычисления по таблицам, что и приводит к запутанности.

angeline
Проблема сумматора оказалась элементарной
Это магическая помощь. Есть такая хрень. Ну, типа чудо, как его называют. Ты куда-то приходишь, тебе что-то желают и у тебя раз и всё получается и рассасываются все проблемы.

Нужно, чтобы один скрипт всё выравнивал правильно, а другой всё правильно по выровненному вычислял, а третий скрипт управлял этими двумя скриптами. Третий скрипт передаёт входной файл в первый скрипт, результат первого скрипта передаёт во второй скрипт, а результат второго скрипта сохраняет в выходной файл. Каждый скрипт должен заниматься только своим делом. Вот тогда будет всё нормально, а иначе будет бесконечно всё ломаться, из-за того что все эти разные действия свалены в одну кучу.



Отредактировано py.user.next (Ноя. 28, 2016 05:23:21)

Офлайн

#8 Ноя. 28, 2016 10:09:31

angeline
Зарегистрирован: 2016-11-11
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

py.user.next
почему у тебя на листе с названием радионуклида перечислены все остальные радионуклиды
Потому что мне нужно провести сравнение измеренений по этому радионуклиду с измерениями по другим и найти соотношения. Именно поэтому на листе с названием радионуклида в строке с его названием стоят либо единицы, либо прочерки, если измерений не было.

py.user.next
Вот там в файлах вместо “-” должна быть пустота, просто пустота. В питоне - это None. А вместо “zero!” должен быть ноль обычный.
Не совсем так с точки зрения моей задачи, но это действительно мелочи

py.user.next
А потом уже, когда эти файлы будут выровнены…
Что Вы вкладываете в понятие “выравнивание”? Если Вы имеете в виду приведение всех входных таблиц к единому размеру, то этого не требуется на мой взгляд, т.к. входные таблицы я не смешиваю. Все безобразие, которое творится в файлах results_111.xls и results_22.xls, родилось на основе одной входной таблицы Data.xls

Хуже, что когда ушла одна ошибка, появилась новая, с которой я вообще не представляю, что делать.
Traceback (most recent call last):
File “Dpyto_p/try5.5.py”, line 12, in <module>
sheet = calc.add_sheet('%s' % r_name, cell_overwrite_ok=True)
File “D:\python\lib\site-packages\xlwt\Workbook.py”, line 368, in add_sheet
raise Exception(“invalid worksheet name %r” % sheetname)
Exception: invalid worksheet name u''

Process finished with exit code 1

При этом часть файлов скармливается питону нормально, а на часть вылезает именно эта ошибка. Запрещенных символов в заголовках нет, это всё те же названия радионуклидов. Длина названия не превышает 31 символа. До этого всё вполне адекватно считывалось и разбиралось на названия страниц, что изменилось сейчас - пока не понимаю. Пример файла, с которым возникает данная проблема.

upd. В этой проблеме оказался виноват excel, а именно сбитые кодировки.

Отредактировано angeline (Ноя. 28, 2016 20:50:44)

Офлайн

#9 Ноя. 29, 2016 08:05:15

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9851
Репутация: +  853  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

Перевёл первый скрипт на функции.



Прикреплённый файлы:
attachment rnukl_v1.0_arch.tar (1010,0 KБ)

Офлайн

#10 Ноя. 29, 2016 18:08:13

angeline
Зарегистрирован: 2016-11-11
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Чем может быть вызвано завышение показаний сумматора?

py.user.next
Перевёл первый скрипт на функции.
Благодарю. Буду разбираться…

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version