【问题标题】:Nested for loop with multiple operations using List Comprehension使用 List Comprehension 嵌套具有多个操作的 for 循环
【发布时间】:2017-03-19 03:27:53
【问题描述】:

只是了解列表理解,因为在最近的一次采访中,技术人员问了我这个问题,作为一个自学者,我回答了 lambda,它不是列表理解。

假设我们有一个时间序列数据“Shiller”,http://us.spindices.com/indices/real-estate/sp-corelogic-case-shiller-us-national-home-price-nsa-index

我使用以下循环计算了 aic/bic:

shiller = [please use some random data or use the link above]

import matplotlib.pyplot as plt
import statsmodels.api as sm
import pandas as pd

def aicbic(shiller):
  arimaijk = []
  aicijk = []
  bicijk = []
  index = []
  for i in range(1,3):
      for j in range(1,2):
          for k in range(0,5):
              arimaijk.append(sm.tsa.ARIMA(shiller,(i,j,k)).fit())
              index.append([i,j,k])
              aicijk.append(arimaijk[k].aic)            
              bicijk.append(arimaijk[k].bic)
  return aicijk, bicijk

aicbic(shiller)
Out[9]: 
([-235.77314152121426,-233.9375761653174,-233.3841011331017,-241.65994870973782,-240.2975620564456,-235.77314152121426,-233.9375761653174,-233.3841011331017,-241.65994870973782,-240.2975620564456],
 [-227.98778197081049,-223.55709676477906,-220.40850188242874,-226.08922960893028,-222.13172310550345,-227.98778197081049,-223.55709676477906,-220.40850188242874,-226.08922960893028,-222.13172310550345])

现在,我想要使用 List Comprehension 得到这个结果,所以我写了以下几行,它们返回错误:

def aicbic(data):    
  arimaijk = []
  aicijk = []
  bicijk = []
  index = []
  [(sm.tsa.ARIMA(data,(i,j,k)).fit(),index.append([i,j,k]),\
  aicijk.append(arimaijk[k].aic),bicijk.append(arimaijk[k].bic)) \
  for i in range(1,3) for j in range(1,2) for k in range(0,5)]

IndexError: 列表索引超出范围

【问题讨论】:

  • 列表理解一次只能构建一个列表。
  • 谢谢斯蒂芬,这个操作有什么替代方案吗?
  • 您可以在此处使用列表推导。你只需要以不同的方式切割它。如果您构建了一个Minimal, Complete, and Verifiable 示例,我会为您完成它。投票结束这个问题的其他人可能也会如此。
  • 添加了一些数据和库,如果您指的是最小、完整和可验证的示例。
  • 为了在这里获得最佳帮助,我们希望能够直接从帖子剪切和粘贴到编辑器中,然后运行代码。具有可验证的结果。然后我们可以更改代码并确保结果仍然很好。如果我们知道什么,通常是工具,而不是您的问题域。因此,您刚刚粘贴了一些名为 shiller 的数据,但您的代码并未引用它。也没有预期的结果。

标签: python loops for-loop list-comprehension


【解决方案1】:

该错误与列表理解本身无关:

[(sm.tsa.ARIMA(data,(i,j,k)).fit(),index.append([i,j,k]),\
  aicijk.append(arimaijk[k].aic),bicijk.append(arimaijk[k].bic)) \
  for i in range(1,3) for j in range(1,2) for k in range(0,5)]

引发错误IndexError: list index out of range 是因为您要访问arimaijk[k]arimaijk 是一个空列表(aicbic(data) 函数的第一行是arimaijk=[])。

【讨论】:

  • 这并不能解决问题。列表推导旨在构建一个列表。此代码使用列表推导的副作用附加到两个列表,从而在列表推导中创建列表。在这种情况下,for 循环将是更好的解决方案。见:stackoverflow.com/questions/5753597/…
  • 我刚刚澄清了IndexError 的原因。无论如何,谢谢你,斯蒂芬。
【解决方案2】:

使用 itertools 和列表推导重铸您的函数:

代码:

import itertools as it

def aicbic(shiller):
    loop = list(it.product(range(1, 3), range(1, 2), range(0, 5)))
    arimaijk = [sm.tsa.ARIMA(shiller, (i, j, k)).fit() for i, j, k in loop]
    aicijk = [arimaijk[k].aic for i, j, k in loop]
    bicijk = [arimaijk[k].bic for i, j, k in loop]
    return aicijk, bicijk

测试代码:

result = aicbic(shiller)

import numpy as np
assert np.all(np.isclose(result, (
    [-235.77314152121426, -233.9375761653174, -233.3841011331017,
     -241.65994870973782, -240.2975620564456, -235.77314152121426,
     -233.9375761653174, -233.3841011331017, -241.65994870973782,
     -240.2975620564456],
    [-227.98778197081049, -223.55709676477906, -220.40850188242874,
     -226.08922960893028, -222.13172310550345, -227.98778197081049,
     -223.55709676477906, -220.40850188242874, -226.08922960893028,
     -222.13172310550345]
)))

注意:

您可能有某种错误,因为 aicijkbicijk 仅依赖于 k

【讨论】:

  • 谢谢斯蒂芬。有趣的解决方案。
【解决方案3】:

感谢 Hossein,我想我现在知道如何使用 List Comprehensions!

def aicbic(data):
  arimaijk = []
  aicijk = []
  bicijk = []
  index = []
  [(arimaijk.append(sm.tsa.ARIMA(data,(i,j,k)).fit()),index.append([i,j,k]),\
  aicijk.append(arimaijk[k].aic),bicijk.append(arimaijk[k].bic)) \
  for i in range(1,3) for j in range(1,2) for k in range(0,5)]
  return aicijk, bicijk


result = aicbic(shiller)

【讨论】:

  • 什么?不,你完全没有抓住重点......如果你的列表理解解决方案是在面试中给出的,你将不会得到这份工作。看在你的份上,请学习我写的内容。
  • 嗨,Stephen,这只是我想了解如何使用 List Comprehension 重新实现它的部分代码。您对仅取决于 k 的代码是正确的。我需要考虑 ARIMA(p,1,q) 中 p 的另一个代码,即“i”。如果你是这个意思。另外,这个问题不是面试的。技术人员只问解释“列表理解”并回答“Lambda”。但显然它不正确。
  • 阅读我对侯赛因回答的回复。认为他的答案是正确的会让你感到困惑。
  • 好的。在列表理解中使用“附加”是没有意义的。你完全正确。感谢斯蒂芬为你的观点辩护。
  • 在我的回答中,我只是澄清了IndexError 的原因。关于列表推导,我同意 Stephen 的观点,即当您不想显式使用列表推导的输出时,应避免使用列表推导。
猜你喜欢
  • 2019-02-18
  • 2018-09-30
  • 2015-10-15
  • 1970-01-01
  • 2021-12-11
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多