【问题标题】:Why do I get a view error when enumerating a Dataframe枚举数据框时为什么会出现视图错误
【发布时间】:2021-02-22 16:48:36
【问题描述】:

为什么会出现“查看”错误:

ndf = pd.DataFrame()
ndf['Signals'] = [1,1,1,1,1,0,0,0,0,0]
signals_diff = ndf.Signals.diff()
ndf['Revals'] = [101,102,105,104,105,106,107,108,109,109]
ndf['Entry'] = 0
for i,element in enumerate(signals_diff):
    if (i==0):
        ndf.iloc[i]['Entry'] = ndf.iloc[i]['Revals']
    elif (element == 0):
            ndf.iloc[i]['Entry'] = ndf.iloc[i - 1]['Entry']
    else:
        ndf.iloc[i]['Entry'] = ndf.iloc[i]['Revals']

试图在数据帧的切片副本上设置值

请参阅文档中的注意事项: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy ndf.iloc[i]['Entry'] = ndf.iloc[i]['Revals']

【问题讨论】:

    标签: python-3.x pandas


    【解决方案1】:

    loc代替iloc

    ndf = pd.DataFrame()
    ndf['Signals'] = [1,1,1,1,1,0,0,0,0,0]
    signals_diff = ndf.Signals.diff()
    ndf['Revals'] = [101,102,105,104,105,106,107,108,109,109]
    ndf['Entry'] = 0
    for i,element in enumerate(signals_diff):
        if (i==0):
            ndf.loc[i,'Entry'] = ndf.loc[i,'Revals']
        elif (element == 0):
                ndf.loc[i,'Entry'] = ndf.loc[i - 1,'Entry']
        else:
            ndf.loc[i,'Entry'] = ndf.loc[i,'Revals']
    

    这将解决问题,但在分配时,索引应该相同。因此,由于索引的原因,您可能无法获得预期的结果。

    【讨论】:

    • 这个解决方案确实给了我正确的答案,但是我需要在一个巨大的数据框(300 万+行)上运行它。有没有办法让这个循环更快?
    • @ManInMoon:那么广红的回答会有所帮助。
    【解决方案2】:

    在尝试分配某些内容时,不要链接像 ndf.iloc[i]['Entry'] 这样的索引。见why does that not work

    也就是说,您的代码可以重写为:

    ndf['Entry'] = ndf['Revals'].where(signals_diff != 0).ffill()
    

    输出:

       Signals  Revals  Entry
    0        1     101  101.0
    1        1     102  101.0
    2        1     105  101.0
    3        1     104  101.0
    4        1     105  101.0
    5        0     106  106.0
    6        0     107  106.0
    7        0     108  106.0
    8        0     109  106.0
    9        0     109  106.0
    

    【讨论】:

    • Hi Quang - 我知道它可以这样写,但这是一个简单的例子。我需要变得更复杂,需要一个迭代解决方案 - 不幸的是
    • @ManInMoon 然后查看 pygirl 的解决方案。一般来说,我会避免循环。为此目的,请查看groupby().shift() 之类的内容。但如果你确定循环是不可避免的,那就继续循环吧。
    • 稍后我需要根据 Revals 的衍生产品更改“Entry”
    • 如果你不能准确地传达你想要做什么和你期望什么,那么循环是你最安全的选择......
    【解决方案3】:

    让我们继续使用index 位置切片和get_indexer

    for i,element in enumerate(signals_diff):
        
        if (i==0):
            ndf.iloc[i,ndf.columns.get_indexer(['Entry'])] = ndf.iloc[i,ndf.columns.get_indexer(['Revals'])]
        elif (element == 0):
                ndf.iloc[i,ndf.columns.get_indexer(['Entry'])] = ndf.iloc[i - 1,ndf.columns.get_indexer(['Entry'])]
        else:
            ndf.iloc[i,ndf.columns.get_indexer(['Entry'])] = ndf.iloc[i,ndf.columns.get_indexer(['Revals'])]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-15
      • 2016-09-11
      • 1970-01-01
      • 2023-03-27
      • 2021-11-26
      • 2018-05-02
      • 2019-10-06
      相关资源
      最近更新 更多