Разделение набора данных на фрагменты и автоматическое вычисление средних значений этих фрагментов

avatar
Dom
8 августа 2021 в 22:20
65
4
0

Мне нужно создать небольшие фрагменты из набора данных. Затем вычислите среднее значение каждого фрагмента. Наконец, создайте список или массив для хранения всех этих средств. Моя цель — автоматизировать процесс. Например: мои данные [2,5,1,5,3,8,4,2,33,65,34,11,42]. Если размер фрагмента равен 3, я ожидаю:

part0 = mydata[0 : 3]  => 2, 5, 1      => mean0 = 2.66
part1 = mydata[3 : 6]  => 5, 3, 8      => mean1 = 5.33
part2 = mydata[6 : 9]  => 4, 2, 33     => mean2 = 13.0
part3 = mydata[9 : 12] => 65, 34, 11   => mean3 = 36.66
part4 = mydata[12 : ]  => 42           => mean4 = 42.0

list_of_means = {mean0, mean1, mean2, mean3, mean4}

Я просто не мог понять, как создать список средств.

Ниже приведен код, который я пытался использовать с помощью цикла For и eval().

import numpy as np
mydata = [2,5,1,5,3,8,4,2,33,65,34,11,42]
chunk_size = 3
index_ref = [n for n in range(len(mydata*1000))]

for i in range(0, len(mydata)):

    globals()[f"part{i}"] ='mydata['+str(index_ref[i*chunk_size])+' : '+str(index_ref[(i*chunk_size)+chunk_size])+']' #This works
    
    globals()[f"mean{i}"] = eval(np.mean(eval('part'+str(i)))) #This brings an error
Источник
cards
8 августа 2021 в 23:53
0

с чего начинается программа? с блоком с импортом или в блоке выше? Не понимаю, почему вы используете глобальные переменные и eval. Это обязательное условие?

cards
9 августа 2021 в 00:02
0

попробуйте eval('np.mean(part+str({i}))') с eval less... Я не пробовал, но удачи

cards
9 августа 2021 в 00:05
0

подобное может повысить производительность range(len(mydata)*1000)

Dom
9 августа 2021 в 09:28
0

Привет @cards, спасибо, что заглянули. Если я сделаю это eval('np.mean(part+str({i}))', это приведет к ошибке, в которой говорится, что «часть» не определена.

cards
9 августа 2021 в 09:29
0

все еще есть проблема?

Dom
9 августа 2021 в 09:31
0

этот диапазон (len (mydata) * 1000) был просто избавлением от ошибки. У меня возникала проблема «вне диапазона», если я использовал только диапазон (len (mydata))

Ответы (4)

avatar
fsimonjetz
9 августа 2021 в 11:14
0

range() может принимать аргументы start, end и step. Таким образом, один из канонических способов получения фрагментов — это сделать что-то вроде этого:

.
# verbose
chunks = []

for i in range(0, len(mydata), chunk_size):
    chunks.append(mydata[i:i+chunk_size])

# or as comprehension
chunks = [mydata[i:i+chunk_size] for i in range(0, len(mydata), chunk_size)]

Затем вычислить среднее значение для каждого элемента, например.

from statistics import mean

list_of_means = [mean(c) for c in chunks]

Общее примечание: возиться с globals и eval для создания экземпляров переменных не только очень многословно и невыполнимо для больших наборов данных, но и довольно хакерски, опасно (поскольку <2986536>7 произвольный может выполняться , потенциально опасный код), и просто не является предпочтительным способом работы с вещами. Если у вас есть куча значений, используйте соответствующую структуру данных, такую ​​как список, словарь или что-то еще, подходящее для ситуации, и обрабатывайте элементы с помощью for-циклов. Если вы получили ошибку индекса, попытайтесь понять, что ее вызывает, вместо того, чтобы использовать специальное исправление, которое не устраняет причину проблемы. Это нужно иметь в виду на будущее — мы все здесь учимся, так держать!

Dom
9 августа 2021 в 16:15
1

Привет @fsimonjetz, ты потрясающий. Огромное спасибо. Это решение обеспечивает все, что мне нужно. Я голосую за это. Ваше общее замечание верно. Я только что понял, что мне нужно быть осторожным с глобальными переменными и eval. В любом случае, я собираюсь опубликовать рабочий код, основанный на моем первоначальном подходе, только для дальнейшего использования. Есть несколько хороших методов, которые я использую для другого приложения. Большое-большое спасибо за помощь. С уважением.

avatar
Dom
21 августа 2021 в 07:49
0

Нампи может помочь. В случае, если вы знаете количество кусков. Вы можете использовать Numpy для создания массива из n фрагментов. Numpy автоматически оценивает размер блока.

import numpy as np
mydata = [2, 5, 1, 5, 3, 8, 4, 2, 33, 65, 34, 11, 42]
mydata = np.array(mydata) #convert list to Numpy array
number_chuncks = 6 #wanted number of chunks
chunks = np.array_split(mydata,number_chuncks)
print('chunks: ', chunks)

Результат:

chunks:  [array([2, 5, 1]), array([5, 3]), array([8, 4]), array([ 2, 33]), array([65, 34]), array([11, 42])]

Ожидаемое количество чанков можно рассчитать следующим образом:

data_length = mydata.size
spacing = np.linspace(0, data_length, number_chuncks)
chunk_size = spacing[1]
print('Expected Chunk size: ',chunk_size)

Результат:

Expected Chunk size:  2.6

Поэтому некоторые фрагменты имеют размер 3, а другие — 2 в массиве фрагментов.

Наконец, средние значения можно рассчитать как:

list_of_means = [np.mean(c) for c in chunks]
print('Means: ',list_of_means)

Результат:

Means:  [ 2.67  4.    6.   17.5  49.5  26.5 ]
avatar
Dom
9 августа 2021 в 16:24
0

Довольно длинное рабочее решение:

mydata = [2,5,1,5,3,8,4,2,33,65,34,11,42,76,12,76,31]

# program - chunker
chunk_size = 3 
remainder = len(mydata) % chunk_size 
chunk_amounts = len(mydata) // chunk_size
if remainder != 0:
    chunk_amounts = len(mydata)//chunk_size + 1
    
# prepare indexing
index_ref = [n for n in range(len(mydata*chunk_amounts))] #to avoid index out of range

# partitioning and mean calculation
for i in range(0, len(mydata)):

    globals()[f"part{i}"] ='mydata['+str(index_ref[i*chunk_size])+' : '+str(index_ref[(i*chunk_size)+chunk_size])+']'
      
    globals()[f"mean{i}"] = np.mean(eval(eval('part'+str(i))))

# build mean list
mean_list = []
for i in range(0, chunk_amounts):
    mean_list.append('mean'+str(i))

# remove quotes in list elements for easier export to numpy array
mean_list = ", ".join(mean_list)
print(mean_list)

Вывод:

'mean0, mean1, mean2, mean3, mean4, mean5'

Постобработка:

mean_array = np.array([mean0, mean1, mean2, mean3, mean4, mean5])
mean_array = mean_array.round(2)
mean_array

Вывод:

[ 2.67,  5.33, 13.  , 36.67, 43.33, 53.5 ]
avatar
cards
9 августа 2021 в 09:35
0

попробуйте это... и скажите, соответствует ли это тому, что вам нужно

# external paramters
data = [2,5,1,5,3,8,4,2,33,65,34,11,42]
chunk_size = 3

# program - chunker
remainder = len(data) % chunk_size
chunk_amounts = len(data) // chunk_size

if remainder != 0:
    chunk_amounts = len(data)//chunk_size + 1

chunks = []
for i in range(chunk_amounts):
    chunk = data[chunk_size * i: chunk_size * (i + 1)]
    mean = sum(chunk)//len(data) # as float, use // for an integer value
    chunks += [mean]

    print(i, chunk, mean)

РЕДАКТИРОВАТЬ С exec

for i in range(0, len(mydata)):

    data_slice = 'mydata[' + str(index_ref[i * chunk_size]) + ' : ' + str(
        index_ref[(i * chunk_size) + chunk_size]) + ']'

    exec(f"part{i} = {data_slice}")
    exec(f'mean{i} = sum(part{i})//3')

print(part2)
print(mean2)

Вывод

[4, 2, 33]
13

РЕДАКТИРОВАТЬ с eval

mydata = [2, 5, 1, 5, 3, 8, 4, 2, 33, 65, 34, 11, 42]
chunk_size = 3
index_ref = [n for n in range(len(mydata*5))]

for i in range(0, len(mydata)):

    data_slice_pattern = 'mydata[' + str(index_ref[i * chunk_size]) + ' : ' + str(
        index_ref[(i * chunk_size) + chunk_size]) + ']'

    globals()[f"part{i}"] = data_slice_pattern
    data_slice = eval(data_slice_pattern)
    globals()[f'mean{i}'] = sum(data_slice)//3

means = [m for m in globals() if 'mean' in m]

print('part2' in globals())
print(eval('part2'))
print('mean2' in globals())
print(eval('mean3'))
print(means)

Вывод

True
mydata[6 : 9]
True
36
['mean0', 'mean1', 'mean2', 'mean3', 'mean4', 'mean5', 'mean6', 'mean7', 'mean8', 'mean9', 'mean10', 'mean11', 'mean12']
cards
9 августа 2021 в 10:44
0

Я не устанавливал numpy, поэтому я использую стандартные библиотеки для среднего. @Dom Дайте мне, пожалуйста, отзыв о «решениях», чтобы я мог их исправить, спасибо

Dom
9 августа 2021 в 16:04
0

Привет @cards, спасибо за помощь, я многому научился из твоего кода. Я не вызывал средства, используя этот метод: означает = [m для m в globals(), если «среднее» в m]. Он приносит любую глобальную переменную, содержащую «среднее». то есть: если у меня было что-то вроде "var_mean", оно также появится... Поэтому я изменил код, чтобы он работал так, как хотел. Однако я убежден, что мой первоначальный подход был не лучшим способом решить вопрос, хотя он и работает. Я собираюсь опубликовать это решение, чтобы показать.

cards
9 августа 2021 в 16:32
0

Рад это слышать! Да, в вашем коде было много неопределенности... и, поскольку я не знал точно, чего вы хотели, я придумал самое ленивое решение means = [m for m in globals() if 'mean' in m]. Лично я предпочитаю держаться подальше от globals, но я принял его как дизайн ограничение :)