【问题标题】:Python numpy - list assignment index out of rangePython numpy - 列表分配索引超出范围
【发布时间】:2019-06-18 03:49:53
【问题描述】:

我有一个以下格式的 CSV 文件

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

为了重现性,我已经包含了完整的CSV file here。从第 1 列开始,我想读取当前行并将其与前一行的值进行比较。如果它更大,我想获取当前值与前一个值的差值并将 (append) 差值存储在列表中。如果当前值等于前一行的值,则继续比较。说明一下第四行(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 文件中有空行吗?
  • 否,CSV 文件中没有空行。

标签: python python-3.x pandas csv numpy


【解决方案1】:

我认为这是一个更好的方法

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])。我们如何才能将负数排除在列表之外?因为我只想保持点亮当前值大于上一行的值。
  • diffs = diffs[diffs > 0] 如果你想删除负值或diffs[diffs < 0] = 0 如果你想将它们设置为零。
  • 如果我想反过来呢?意思是,当当前行值是less than上一行值时?我是这样做的:np.median(diffs[diffs>0]) 但我得到的数组列表值是 negative 数字 - [-71 -37 -2] -37.0
  • diffs = np.diff(df[0])*-1 返回` [ 71, -4, -33, 37, 2, -5, -2, -29, -217]` np.median(diffs[diffs>0]) 应该返回 37.0 这是什么你希望吗?
  • @AnanayMital,否 - 您在答案中所做的增加部分是正确的。但我试图做与我提出的问题相反的事情——如果我们想在当前值smaller 比之前的值时这样做会发生什么?对于这个(相反的部分),我期望得到[-71 -37 -2]-37.0 的中值。
【解决方案2】:

使用熊猫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

【讨论】:

    【解决方案3】:

    基本上,np.diff() 需要一个类似输入的列表,而您传递的是一个整数。这就是它失败的原因

    【讨论】:

      【解决方案4】:

      技术上我们不需要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
      

      【讨论】:

      • 但是,如 Ananay Mital 所示,在 99% 的情况下,使用 numpy 比对数字数据使用列表更可取。
      • 这取决于用例,但说 99% 的案例是过度的,这个小数据是微不足道的,我们可以同意不同意
      • 这很好,但是res = [abs(sub(*t)) for t in zip(nums, nums[1:]) if lt(*t)] 行在 Python3 上说 Invalid syntax
      • @aws_apprentice,[4, 33, 5, 2, 29, 217] 列表中的5 来自哪里?我很迷惑。如果我手动执行,我会得到 5 个值。
      • @Brown 您提供的样本数据有 13,然后是 18,因此是 5
      【解决方案5】:

      你得到的原因

      IndexError: 列表赋值索引超出范围

      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
      【解决方案6】:

      您遇到的问题是,当您尝试运行 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
      • 您是否希望您的结果始终是积极的?
      • 是的,我希望我的所有结果都是积极的。
      • 我刚刚进行了更新,将 abs 包含在 np_median 变量中,这将使所有结果为正。
      • 它打印整个列表array([185, 4, 33, 219, 254, 5, 2, 29, 217], dtype=uint8),我认为这是不正确的。对于增加的部分,它应该只打印[4, 33, 5, 2, 29, 219]。我在对您的回答的第一条评论中提出的问题也应该打印[-71 -37 -2]
      猜你喜欢
      • 2013-05-31
      • 1970-01-01
      • 2018-10-21
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-19
      • 1970-01-01
      相关资源
      最近更新 更多