【问题标题】:pandas multiindex dataframe, ND interpolation for missing valuespandas 多索引数据帧,缺失值的 ND 插值
【发布时间】:2015-06-10 12:05:38
【问题描述】:

是否可以在 pandas 中插入多索引数据帧中的缺失值。下面的这个例子没有按预期工作:

arr1=np.array(np.arange(1.,10.,1.))
arr2=np.array(np.arange(2.,20.,2.))
df1=pd.DataFrame(zip(arr1,arr2,arr1+arr2,arr1*arr2),columns=['x','y','xplusy','xtimesy'])

df1.set_index(['x','y'],inplace=True)

df2=df1.reindex(index=zip(*df1.index.levels)+[(2,2),(3,2),(5,5)])
df2.sortlevel([0,1],inplace=True)
df2.interpolate(method='linear',inplace=True)

在 xplusy 和 xtimesy 列中显示的不是我所期望的添加索引。

-----------  ----  ---
(1.0, 2.0)    3      2
(2.0, 2.0)    4.5    5
(2.0, 4.0)    6      8
(3.0, 2.0)    7.5   13
(3.0, 6.0)    9     18
(4.0, 8.0)   12     32
(5.0, 5.0)   13.5   41
(5.0, 10.0)  15     50
(6.0, 12.0)  18     72
(7.0, 14.0)  21     98
(8.0, 16.0)  24    128
(9.0, 18.0)  27    162
-----------  ----  ---

【问题讨论】:

    标签: python numpy pandas scipy interpolation


    【解决方案1】:

    所以在填充缺失值之前,这就是前几行中的内容:

    df2
    
          xplusy  xtimesy
    x y                  
    1 2        3        2
    2 2      NaN      NaN
      4        6        8
    

    您似乎想根据 MultiIndex 进行插值。我不相信有任何方法可以使用 pandas interpolate 来做到这一点,但你可以基于一个简单的索引来做到这一点(method='linear' 忽略索引 btw 并且也是默认的,所以也不需要指定它):

    df2.reset_index(level=1).interpolate(method='index')
    
        y  xplusy  xtimesy
    x                     
    1   2       3        2
    2   2       6        8
    2   4       6        8
    
    df2.reset_index(level=0).interpolate(method='index')
    
        x  xplusy  xtimesy
    y                     
    2   1     3.0        2
    2   2     3.0        2
    4   2     6.0        8
    

    显然,在这种情况下,您可以分多个步骤创建 xplusy 和 xtimesy(首先是 x,然后是 y,然后是 xplusy 和 xtimesy),但我不确定这是否是您真正想要做的。

    无论如何,这是一种您可以使用 pandas interpolate 轻松完成的一维插值。如果这还不够,您可以先查看 numpy 的 interp2d

    【讨论】:

    • 我正在寻找 scipy 中的 griddata 等 ND 插值
    • @denfromufa -- 你应该把它添加到问题中。我还将 numpy 添加为标签(而不是数据框)。您可能也想从问题中删除 pandas interpolate ,因为它看起来在这里没有任何用处。当然,只是建议。
    【解决方案2】:
    def multireindex(_df, new_multi_index, method='linear',copy=True):
        #from scipy.interpolate import griddata
        #import numpy as np
        #import pandas as pd
        _points=np.array(_df.index.values.tolist())
        dfn=dict()
        for aclm in _df.columns:
            dfn[aclm] = griddata(_points, _df[aclm], 
                            np.array(new_multi_index), method=method)
        dfn=pd.DataFrame(dfn,index=pd.MultiIndex.from_tuples(
                new_multi_index,names=_df.index.names))
        return pd.concat([dfn,_df])
    
    import pandas as pd
    import numpy as np
    #import numpy.random as npr
    #df1=pd.DataFrame(npr.rand(10,5))
    arr1=np.random.rand(100)
    arr2=np.random.rand(100)
    arr1,arr2=[np.round(a*b) for a,b in 
                    zip([arr1,arr2],[100,100,1000])]
    df1=pd.DataFrame(zip(arr1,arr2,arr1+arr2,arr1*arr2),columns=['x','y','plus','times'])
    df1.set_index(['x','y'],inplace=True)
    from scipy.interpolate import griddata
    new_points=[(20.0,20.0),(25.0,25.0)]
    df2=multireindex(df1,new_points)
    df2.head()
    

    【讨论】:

      【解决方案3】:

      根据你有多少行,有不同的方法。

      我曾经在我的 MAC Pro(16G RAM)上处理一个包含 7000 万行的数据集。我必须按 product_id、client_id 和周数对行进行分组,以计算客户的需求。就像你的例子一样,这个数据集没有每周的所有产品。所以我尝试了这些方法:

      1. 查找每个产品缺少的周数,填写并重新索引。即使我将数据集分成几部分,返回结果也需要太多时间和内存。

      2. 查找每个产品缺少的周数,制作一个新的数据框,并与原始数据框连接。效率更高,但仍然使用过多的时间(几个小时)和内存。

      3. 毕竟,我在 Stackoverflow 上找到了this post。我尝试在空的周内取消堆叠周数,用“-9999”(一个不存在的数字)填充并再次堆叠。之后我用 np.nan 替换“-9999”,然后我得到了我想要的。只需几分钟即可完成。我认为这是正确的做法。

      作为结论,如果你的资源有限,“reindex”可以只用于一个小数据集(我使用第一种方法来处理一个有 500 万行的片段,它会在几分钟内返回),除了“unstack/stack " 应该适用于更大的数据框。

      【讨论】:

        猜你喜欢
        • 2019-05-16
        • 1970-01-01
        • 2019-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 2017-06-20
        相关资源
        最近更新 更多