python-3.x - 滚动窗口问题 : ValueError: Length of passed values is 3, 索引意味着 2

标签 python-3.x pandas

我正面临 Pandas 的以下问题,无法识别出任何错误。

churned_or_dormant_customers_by_month = jobs_by_customer_and_month.fillna(0).rolling(2, 2, axis='columns').apply(lambda window: 1 if not window[1] and window[0] else 0).sum(skipna=True)

上面给出了以下回溯:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python3.8/site-packages/pandas/core/window/rolling.py", line 2059, in apply
    return super().apply(
  File "/usr/lib/python3.8/site-packages/pandas/core/window/rolling.py", line 1388, in apply
    return self._apply(
  File "/usr/lib/python3.8/site-packages/pandas/core/window/rolling.py", line 586, in _apply
    result = np.apply_along_axis(calc, self.axis, values)
  File "<__array_function__ internals>", line 5, in apply_along_axis
  File "/usr/lib/python3.8/site-packages/numpy/lib/shape_base.py", line 379, in apply_along_axis
    res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))
  File "/usr/lib/python3.8/site-packages/pandas/core/window/rolling.py", line 576, in calc
    return func(x, start, end, min_periods)
  File "/usr/lib/python3.8/site-packages/pandas/core/window/rolling.py", line 1414, in apply_func
    values = Series(values, index=self.obj.index)
  File "/usr/lib/python3.8/site-packages/pandas/core/series.py", line 313, in __init__
    raise ValueError(
ValueError: Length of passed values is 3, index implies 2.

我确定这不是错误,但我在使用滚动窗口功能时犯了一个愚蠢的错误。虽然我无法弄清楚错误是什么,但我可以发誓这适用于以前版本的 Pandas。这提醒了我,我运行这段代码的版本是 1.1.0rc0

pickle 格式的示例数据是 here .看起来像这样:

>>> jobs_by_customer_and_month
     2019-1  2019-2  2019-3
1.0     1.0     1.0     1.0
2.0     2.0     2.5     2.1

最佳答案

任何低于 0.23 的版本,值总是作为 ndarray 传递。 rolling apply 的选项 raw 是从 0.23+ 版本开始实现的。从0.23版本到<1.0.0版本,raw默认为True。但是,它会产生警告:

C:\Python\Python37-32\Scripts\ipython:3: FutureWarning: Currently, 'apply' passes
the values as ndarrays to the applied function. In the future, this will change
to passing it as Series objects. You need to specify 'raw=True' to keep the current 
behaviour, and you can pass 'raw=False' to silence this warning

您在旧 pandas 上没有看到任何错误或警告,所以我猜您的旧版本是 < 0.23。

从 1.0.0+ 版本开始,rolling 正式默认将值作为 series(即 raw=False)传递给 apply

关于你的错误,我猜这是一个错误,它只会在 沿 axis = 1 滚动应用时出现。

我检查了 0.24 版本,这个错误已经存在。因此,它可能出现在将值作为 series 传递给滚动对象 apply 的实现过程中。但是,只有当 rolling apply 沿 columns(换句话说,axis=1)时才会出现此错误。

rolling apply 沿 axis = 1series 作为值传递,每个系列都是 df 中的一行。在您的情况下,它的长度 = 3。即它是 df.shape[1]

df: 
     2019-1  2019-2  2019-3
1.0     1.0     1.0     1.0
2.0     2.0     2.5     2.1

In [13]: df.loc[1.0].size
Out[13]: 3

In [14]: df.shape[1]
Out[14]: 3

看看上面的错误回溯:

...
File "/usr/lib/python3.8/site-packages/pandas/core/window/rolling.py", line 1414, in apply_func
    values = Series(values, index=self.obj.index)
...

它尝试从 values 构建一个系列,并使用 self.obj.index 作为索引。 self 是滚动对象,obj 是它的属性。让我们检查一下 obj 的值是什么:

In [17]: (df.fillna(0)
    ...:    .rolling(window=3, axis='columns').__dict__
    ...:    )
Out[17]:
{'obj':      2019-1  2019-2  2019-3
 1.0     1.0     1.0     1.0
 2.0     2.0     2.5     2.1,
 'on': None,
 'closed': None,
 'window': 3,
 'min_periods': None,
 'center': False,
 'win_type': None,
 'win_freq': None,
 'axis': 1,
 '_cache': {'_on': Index(['2019-1', '2019-2', '2019-3'], dtype='object'),
  'is_datetimelike': False},
 '_numba_func_cache': {}}

所以,self.obj 就是 df 本身。这意味着 self.obj.indexdf.index 并且它的长度是 2

In [19]: df.index.size
Out[19]: 2

series 的构造根据index 的长度检查数据的长度(在文件series.py 内)

...
if index is None:
    if not is_list_like(data):
        data = [data]
        index = ibase.default_index(len(data))
elif is_list_like(data):

    # a scalar numpy array is list-like but doesn't
    # have a proper length
    try:
        if len(index) != len(data):
            raise ValueError(
                f"Length of passed values is {len(data)}, "
                f"index implies {len(index)}."
            )
    except TypeError:
        pass
...

如您所见,每行的长度为 3,而 df.index 的长度为 2,因此会抛出 ValueError。

这是一个错误,所以与此同时,您需要使用参数 raw = True 指定您的rolling apply 来解决这个问题

关于python-3.x - 滚动窗口问题 : ValueError: Length of passed values is 3, 索引意味着 2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63155830/

相关文章:

python - 将每对列彼此分开

python - 将月末或周末系列转换为每日系列

python - Pandas "cut"基于其他列

当进程数和工作线程数增加时,Python 多处理池 API 无法有效工作

python - 'numpy.float6 4' object has no attribute ' 应用'

python-3.x - python / Pandas : why the empty dataframe when using isin?

python - 使用相同的键、多个值追加到字典

python - 数据透视表中 Y 相对于 Y 的变化

python - Pandas 数据框中值的组合

performance - Python GUI (tkinter.ttk) 应用程序速度慢