Таблица последовательности Tribonacci используя NumPy и панды


То, что я пытаюсь сделать, это рассчитать число Tribonacci и соотношение. Я могу сделать это в Excel легко, как это.

Image 1

Image 2

Так что я попытался сделать то же самое с помощью Python 3 сейчас. Она работает и дает такой выход.

Image 3

Но не могли бы вы быть так добры, чтобы проверить код и посмотреть, какие явные ошибки вы видите в нем и посоветуйте на что лучше, как я не хочу продолжать кодирование, если моя логика для решения таких проблем в корне не верно, где-то.

Приоритетами для меня являются время выполнения и читабельности, я думаю

Что бы вы сделали иначе и почему? Я знаю, это может выглядеть как беспорядок. Из того, что я слышал с помощью Exec и eval (код строки) плохие идеи, а также что функция звонки дорогие?

Мне не нравится мой код вообще особенно как следующий() используется так много раз, но надеюсь, вы видите, как я думал, пытаясь повторить таблицу Excel

Чтобы выполнить код, который нужно NumPy и панды

import pandas as pd
import numpy as np

column_names = ["Number sequence", "Ratio"]
column_counter = len(column_names) -1
header_columns = ['']
while column_counter >= 0:
    column_counter = column_counter - 1
    header_columns.append(column_names[column_counter])

tribonacci_numbers = [0,1]    
tribonacci_counter = 19 #Reach
while tribonacci_counter -1 >= 0:
    tribonacci_counter = tribonacci_counter - 1
    tribonacci_numbers.append(sum(tribonacci_numbers[-3:]))
tribonaccis_list_length = len(tribonacci_numbers)-1

index_builder = 1
rows = []
while index_builder <= tribonaccis_list_length:
    try:
        index_builder = index_builder + 1
        rows.append((["Number: "+str(index_builder),tribonacci_numbers[index_builder],tribonacci_numbers[index_builder]/tribonacci_numbers[index_builder-1]]))       
    except IndexError:
        continue

def get_row():
    the_row = [x for x in rows]
    row_counter = 0
    while row_counter <= len(the_row):
        try:
            row_counter = row_counter + 1
            yield (the_row[row_counter])            
        except IndexError:
            continue

a = get_row()
def therow():
    for q in a:
        yield q

datas = np.array([
header_columns,
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow()),
next(therow())])

df = pd.DataFrame(data=datas[1:,1:],index=datas[1:,0],columns=datas[0,1:])
print(df)

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



Комментарии
3 ответа

Вы используете неправильный инструмент для работы. В принципе, вы делаете все вычисления в Python, использовать numpy для промежуточного хранения и pandas для дисплея.

Вместо этого, вы должны вычислить список tribonacci чисел и оттуда по применению pandas для всего остального, как это было бы гораздо более эффективным / читаем. Я бы продолжайте строить tribonacci чисел в Python, как я не знаю достаточно pandas уметь придумать эффективный способ, что бы не привлекать Dataframe.append а также потому, что она может быть выражена очень красиво в качестве генератора:

def tribonacci_sequence():
a, b, c = 0, 1, 1
yield a
yield b
while True:
yield c
a, b, c = b, c, a + b + c

Затем вы можете выбрать количество чисел вам, как с помощью itertools.islice и дать им pandas.Dataframe.

Оттуда, вы можете легко вычислить коэффициент смещения таблицы данных и разделительный элемент-мудрый:

def compute_tribonacci(upper_limit, skip_first_rows=3):
tribonacci = list(islice(tribonacci_sequence(), upper_limit + 1))
df = pd.DataFrame({'Number sequence': tribonacci})
df['Ratio'] = df['Number sequence'] / df.shift(1)['Number sequence']
df.index = df.index.map('Number: {}'.format)
return df.iloc[skip_first_rows:]

Последнее, что нужно сделать, это задать определенное количество строк. Полный код:

from itertools import islice
import pandas as pd

def tribonacci_sequence():
a, b, c = 0, 1, 1
yield a
yield b
while True:
yield c
a, b, c = b, c, a + b + c

def compute_tribonacci(upper_limit, skip_first_rows=3):
tribonacci = list(islice(tribonacci_sequence(), upper_limit + 1))
df = pd.DataFrame({'Number sequence': tribonacci})
df['Ratio'] = df['Number sequence'] / df.shift(1)['Number sequence']
df.index = df.index.map('Number: {}'.format)
return df.iloc[skip_first_rows:]

if __name__ == '__main__':
df = compute_tribonacci(50)
print(df)

11
ответ дан 29 января 2018 в 04:01 Источник Поделиться

Некоторые общие советы

Размещайте код в функции

Таким образом, вы можете проверить каждую часть по отдельности. Здесь генерация последовательности, вычисление отношения и экспорт в панды четкие разграничения в функциональность вашего кода

Генераторы

Лучшие алгоритмы реализации последовательности Фибоначчи в качестве генераторов

с пределом

def fib(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b

или бесконечные

def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b

Адаптация это tribonacci должно быть тривиальным

def trib():
a, b, c = 0, 1, 1
while True:
yield a
a, b, c = b, c, a + b + c

или более обобщенно:

def generalised_fibonacci(max_len = 2, begin_data = None):
from collections import deque
if begin_data is None:
begin_data = [0] + [1] * (max_len-1)
data = deque(begin_data, max_len)
while True:
# print(data)
a = data.popleft()
yield a
data.append(a + sum(data))

оптимизирован для @реплика накоплений

def generalised_fibonacci(max_len = 2, begin_data = None):
from collections import deque
if begin_data is None:
begin_data = [0] + [1] * (max_len - 1) + [max_len - 1]
data = deque(begin_data, max_len + 1)
while True:
a = data.popleft()
yield a
# print(a, data)
data.append(2 * data[-1] - a)

Сделать это в панд

вот список и itertools.islice ваши друзья

def get_trib(num_items)
trib_nums = list(itertools.islice(trib(3), num_items + 1))
return pd.DataFrame(data=trib_nums, index = range(num_items))

рассчитать коэффициенты

панды имеет простой DataFrame.shift methodно это тоже можно вычислить его до введения в таблицы данных

def trib_ratio(num_items):

trib_generator = itertools.islice(generalised_fibonacci(3), num_items + 1)
trib_gen, trib_gen2 = itertools.tee(trib_generator, 2)
yield next(trib_gen), None

for trib, trib2 in zip(trib_gen, trib_gen2):
ratio = trib / trib2 if trib2 else None # prevent zerodivision on first element
yield trib, ratio


pd.DataFrame(list(trib_ratio(20)), columns=['trib', 'ratio'])

    trib    ratio
0 0
1 1
2 1 1.0
3 2 2.0
4 4 2.0
5 7 1.75
6 13 1.8571428571428572
7 24 1.8461538461538463
8 44 1.8333333333333333
9 81 1.8409090909090908
10 149 1.8395061728395061
11 274 1.8389261744966443
12 504 1.8394160583941606
13 927 1.8392857142857142
14 1705 1.8392664509169363
15 3136 1.8392961876832845
16 5768 1.8392857142857142
17 10609 1.8392857142857142
18 19513 1.8392873974926949
19 35890 1.8392866294265362
20 66012 1.8392867093898022

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

6
ответ дан 29 января 2018 в 05:01 Источник Поделиться

Создать таблицу данных с именами столбцов:

df = pd.DataFrame(columns=['Number sequence', 'Ratio'])

Построить в каждой строке:

for row_number in range(4,number_of_rows):
row_name = 'Number: {}'.format(row_number)
dropped_number = df.loc['Number: {}'.format(row_number-4),'Number Sequence']
current_number = 2*previous_number-dropped_number
df.loc[row_name,'Number Sequence'] = current_number
df.loc[row_name,'Ratio'] = current_number/previous_number
previous_number = current_number

если у вас возникли проблемы с пониманием current_number = 2*previous_number-last_numberрассмотрим случай генерации 7-й ряд. Это будет 4+7+13. Но 13 был рассчитан на 13 = 2+4+7. Поэтому 7 число 4+7+(2+4+7) = 2*(2+4+7)-2, что на 2*(6-й номер) - 3-го числа. Так что энное число 2*(Н-1) - й ряд - (П-4)м номером.

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

Вы также должны инициализировать previous_number нужное значение.

3
ответ дан 29 января 2018 в 11:01 Источник Поделиться