Python numpy - индекс присвоения списка вне диапазона

У меня есть файл CSV следующего формата

86,1
15,2
19,3
52,4
15,5
13,6
18,7
20,8
49,9
266,10

Для воспроизводимости я включил полный CSV-файл здесь. Из столбца 1 я хотел прочитать текущую строку и сравнить ее со значением предыдущей строки. Если оно больше, я хотел взять разницу текущего значения от предыдущего и сохранить (append) разницу в списке. Если текущее значение равно значению предыдущей строки, продолжайте сравнение. Поясню. Например, в приведенном выше образце записи, который я предоставил, третья строка (19) больше, чем значение во второй строке (15) - поэтому будет (19-15 =4), четвертая строка (52-19 = 33), и Т. Д.

Вот мой простой подход с использованием numpy

import numpy as np
import pandas as pd
import csv

df = pd.read_csv("testdata.csv")
with open("testdata.csv") as f:
    reader = csv.reader(f, delimiter = ",")
    for i in reader:
        print (i[0])
        diffs=np.diff(i[0])
        increased_value=np.median(diffs[diffs>0])

Однако я получаю сообщение об ошибке IndexError: list assignment index out of range. Как я могу исправить эту ошибку, чтобы решить задачу, которую я упомянул?

в вашем CSV-файле есть пустые строки?

Kannappan Sirchabesan 24.01.2019 13:06

НЕТ, в файле CSV НЕТ пустых строк.

user10553396 24.01.2019 13:06
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
2
644
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Я думаю, что это лучший способ

df = pd.read_csv("testdata.csv", header=None)
df
     0     1
0   86     1
1   15     2
2   19     3
3   52     4
4   15     5
5   13     6
6   18     7
7   20     8
8   49     9
9   266   10

diffs = np.diff(df[0])
increased_value = np.median(diffs[diffs>0])
increased_value

17.0

Это круто! Однако, если вы напечатаете diffs, он выдаст array([-71, 4, 33, -37, -2, 5, 2, 29, 217]). Как мы можем исключить отрицательные числа из списка? Поскольку я хочу, чтобы ТОЛЬКО текущее значение было больше, чем значение предыдущей строки.

user10553396 24.01.2019 13:31
diffs = diffs[diffs > 0], если вы хотите отбросить отрицательные значения, или diffs[diffs < 0] = 0, если вы хотите установить их равными нулю.
JE_Muc 24.01.2019 13:33

А если я хочу сделать наоборот? Значение, когда текущее значение строки равно less than предыдущему значению строки? Я сделал это так: np.median(diffs[diffs>0]), но значения списка массивов, которые я получаю, являются числами negative - [-71 -37 -2] -37.0

user10553396 24.01.2019 15:19
diffs = np.diff(df[0])*-1 возвращает` [ 71, -4, -33, 37, 2, -5, -2, -29, -217]` np.median(diffs[diffs>0]) должен возвращать 37.0 Это то, на что вы надеялись?
Ananay Mital 24.01.2019 16:40

@AanayMital, НЕТ - растущая часть, как вы это сделали в своем ответе, верна. Но я пытался сделать противоположное заданному мной вопросу — что произойдет, если мы захотим сделать это, когда текущее значение будет smaller, чем предыдущее значение? Для этого (обратная часть) я ожидал получить [-71 -37 -2] и среднее значение -37.0.

user10553396 24.01.2019 20:59

да, это просто np.median(diffs[diffs<0]). Правильно?

Ananay Mital 25.01.2019 04:46

По сути, np.diff() ожидает список, похожий на ввод, и то, что вы передаете, является целым числом. Вот почему это не удается

Нам технически не нужен numpy

from statistics import median
from operator import itemgetter, lt, sub

first = itemgetter(0)
nums = []

with open('testdata.csv', 'r') as fin:
    reader = csv.reader(fin)
    for line in reader:
        nums.append(int(first(line)))

res = [abs(sub(*t)) for t in zip(nums, nums[1:]) if lt(*t)]

[4, 33, 5, 2, 29, 217]

median(res)

17.0

Но использование numpy, как показал Ананай Митал, в 99% случаев предпочтительнее использования списков для числовых данных.

JE_Muc 24.01.2019 13:25

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

gold_cy 24.01.2019 13:26

Это здорово, но строка res = [abs(sub(*t)) for t in zip(nums, nums[1:]) if lt(*t)] говорит Invalid syntax на Python3.

user10553396 24.01.2019 13:28

@aws_apprentice, откуда 5 в списке [4, 33, 5, 2, 29, 217]? Я смущен. Если я сделаю это вручную, вместо этого я получу 5 значений.

user10553396 24.01.2019 14:08

@Brown предоставленные вами образцы данных имеют 13, а затем 18, следовательно, 5

gold_cy 24.01.2019 14:29

Причина, по которой вы получаете

IndexError: list assignment index out of range

np.diff() принимает входные данные, такие как массив или список.

Нравится

arr = []
df = pd.read_csv("testdata3.csv")
df
with open("testdata3.csv", mode='r', encoding='utf-8-sig') as f:
    reader = csv.reader(f, delimiter = ",")
    for i in reader:
#         print(i[0])
        arr.append(int(i[0]))

diffs=abs(np.diff(arr))
increased_value=np.median(diffs[diffs>0])

А если я хочу сделать наоборот? Значение, когда текущее значение строки равно less than предыдущему значению строки? Я сделал это так: np.median(diffs[diffs>0]), но значения списка массивов, которые я получаю, являются числами negative - [-71 -37 -2] -37.0

user10553396 24.01.2019 15:20

Использование панд s.diff():

data = StringIO("""86,1
15,2
19,3
52,4
15,5
13,6
18,7
20,8
49,9
266,10""")

df=pd.read_csv(data,header=None)

m1=df[0].diff().fillna(0)
#m1[m1>0].tolist()
#[4.0, 33.0, 5.0, 2.0, 29.0, 217.0]
m1[m1>0].median()
#17.0

Проблема, с которой вы столкнулись, заключается в том, что когда вы пытаетесь запустить np.diff, типом dtype по умолчанию для вашего массива является dtype U3, что означает, что значения в вашем массиве не являются числами, что означает, что требуется преобразование. Попробуйте следующее:

with open("test_data.csv", "r") as f:
    reader = csv.reader(f) ## no need for delimiter if your delimiter is ','
    data = []
    for row in reader:
        data.append(row[0])

## ensure that you convert your data into numpy array with appropriate data type 
## before carrying out any mathematical operations 

np_array = np.array(data, dtype=np.uint8) 
np_diff = np.diff(np_array)
np_median = abs(np.median(np_diff[np_diff > 0]))

print(np_median)

Если вам нужно делать это регулярно, вы всегда можете обернуть этот метод вокруг. Попробуйте это.

А если я хочу сделать наоборот? Значение, когда текущее значение строки равно less than предыдущему значению строки? Я сделал это так: np.median(diffs[diffs>0]), но значения списка массивов, которые я получаю, являются числами negative - [-71 -37 -2] -37.0

user10553396 24.01.2019 15:20

Вы ожидаете, что ваш результат всегда будет положительным?

Naufal 24.01.2019 19:01

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

user10553396 24.01.2019 19:16

Я только что сделал обновление, чтобы включить abs в переменную np_median, что сделает все результаты положительными.

Naufal 24.01.2019 19:32

он печатает весь список array([185, 4, 33, 219, 254, 5, 2, 29, 217], dtype=uint8), что я не думаю, что это правильно. Для возрастающей части он должен вместо этого печатать только [4, 33, 5, 2, 29, 219]. Вопрос, который я задал в своем первом комментарии к вашему ответу, также должен печатать [-71 -37 -2].

user10553396 24.01.2019 20:49

Извините за задержку с ответом. Я только что попытался использовать обычный список, содержащий ваши числа, т.е. данные = [(86,1),(15,2),(19,3),(52,4), (15,5), (13,6), (18,7), (20,8),(49,9),(266,10)], а затем перебрали, чтобы получить список a = [86, 15, 19, 52, 15, 13, 18, 20 , 49, 266]. Затем я преобразовал это в массив numpy, а затем применил diff для получения массива ([185, 4, 33, 219, 254, 5, 2, 29, 217], dtype = uint8). С этого момента я использовал abs(np.median(np_diff[np_diff > 0])), что дает мне 33,0. Для вашего комментария о том, что текущее значение меньше предыдущего значения, вам нужно будет отсортировать ваши данные, т.е. отсортировать (данные).

Naufal 30.01.2019 13:55

diffs[diffs > 0] является только фильтром и на самом деле не сообщает вам, меньше ли текущее значение строки, чем значение предыдущей строки. Для этого вам нужно будет сделать петлю.

Naufal 30.01.2019 13:57

Другие вопросы по теме