代码之家  ›  专栏  ›  技术社区  ›  vestland

如何有效地过滤熊猫数据帧并返回熊猫序列?

  •  0
  • vestland  · 技术社区  · 6 年前

    这个问题似乎很简单,可以说是近乎愚蠢。但考虑到我的场景,我似乎必须这样做,以保持跨多个数据帧的一系列计算的效率。

    脚本:

    我有一堆pandas数据帧,其中列名由名称部分和时间部分构成,例如 'AA_2018' 'BB_2017' . 我对不同数据帧的不同列进行计算,所以我必须过滤掉时间段。作为一个 mcve 我想把包含 'AA' 从包含 'BB' 并忽略此数据帧中的所有其他列:

    import pandas as pd
    import numpy as np
    
    dates = pd.date_range('20180101',periods=3)
    df = pd.DataFrame(np.random.randn(3,3),index=dates,columns=['AA_2018', 'AB_2018', 'BB_2017'])
    

    enter image description here

    diff_series = df['AA_2018'] - df['BB_2017']
    

    这将返回一个熊猫系列,因为我使用单括号 [] 如果我用了双括号的话,那就不是datframe了 [[]] .

    我的挑战:

    diff_series pandas.core.series.Series . 但既然我有一些过滤工作要做,我就用 df.filter() 返回一个包含一列和 a系列:

    # in:
    colAA = df.filter(like = 'AA')
    
    # out:
    # AA_2018
    # 2018-01-01  0.801295
    # 2018-01-02  0.860808
    # 2018-01-03 -0.728886
    
    # in:
    # type(colAA)
    
    # out:
    # pandas.core.frame.DataFrame
    

    Snce公司 colAA 属于类型 pandas.core.frame.DataFrame ,下面也返回一个数据帧:

    # in:
    colAA = df.filter(like = 'AA')
    colBB = df.filter(like = 'BB')
    df_filtered = colBB - colAA
    
    # out:
                AA_2018  BB_2017
    2018-01-01      NaN      NaN
    2018-01-02      NaN      NaN
    2018-01-03      NaN      NaN    
    

    这不是我想要的。这是:

    # in: 
    diff_series = df['AA_2018'] - df['BB_2017']
    
    # out:
    2018-01-01    0.828895
    2018-01-02   -1.153436
    2018-01-03   -1.159985
    

    为什么我要这么做?

    因为我想用 .to_frame() 使用基于我使用的过滤器的指定名称。

    我认为低效的方法是:

    # in:
    
    colAA_values = [item for sublist in colAA.values for item in sublist]
    # (because colAA.values returns a list of lists)
    
    colBB_values = [item for sublist in colBB.values for item in sublist]
    
    serAA = pd.Series(colAA_values, colAA.index)
    serBB = pd.Series(colBB_values, colBB.index)
    
    df_diff = (serBB - serAA).to_frame(name = 'someFilter')
    
    # out:
    
                  someFilter
    2018-01-01   -0.828895
    2018-01-02    1.153436
    2018-01-03    1.159985
    

    我尝试的/我希望的工作:

    # in:
    (df.filter(like = 'BB') - df.filter(like = 'AA')).to_frame(name = 'somefilter')
    
    # out:
    # AttributeError: 'DataFrame' object has no attribute 'to_frame'
    
    # (Of course because df.filter() returns a one-column dataframe)
    

    df.filter() 可能会退回熊猫系列,但不会。

    我想我可以问这样的问题: How to convert pandas dataframe column to a pandas series? 但这似乎也没有一个高效的内置单行线。大多数搜索结果的处理方式相反。我已经花了相当长的时间来处理潜在的解决方案,一个显而易见的解决方案可能就在眼前,但我希望你们中的一些人能就如何有效地做到这一点提出建议。

    import pandas as pd
    import numpy as np
    
    dates = pd.date_range('20180101',periods=3)
    df = pd.DataFrame(np.random.randn(3,3),index=dates,columns=['AA_2018', 'AB_2018', 'BB_2017'])
    
    #diff_series = df[['AA_2018']] - df[['BB_2017']]
    #type(diff_series)
    
    colAA = df.filter(like = 'AA')
    colBB = df.filter(like = 'BB')
    df_filtered = colBB - colAA
    
    #type(df_filtered)
    #type(colAA)
    #colAA.values
    
    #colAA.values returns a list of lists that has to be flattened for use in pd.Series
    colAA_values = [item for sublist in colAA.values for item in sublist]
    colBB_values = [item for sublist in colBB.values for item in sublist]
    
    serAA = pd.Series(colAA_values, colAA.index)
    serBB = pd.Series(colBB_values, colBB.index)
    
    df_diff = (serBB - serAA).to_frame(name = 'someFilter')
    
    # Attempts:
    # (df.filter(like = 'BB') - df.filter(like = 'AA')).to_frame(name = 'somefilter')
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   jezrael    6 年前

    你需要相反的 to_frame DataFrame.squeeze -转换一列 DataFrame Series :

    colAA = df.filter(like = 'AA')
    colBB = df.filter(like = 'BB')
    df_filtered = colBB.squeeze() - colAA.squeeze()
    print (df_filtered)
    2018-01-01   -0.479247
    2018-01-02   -3.801711
    2018-01-03    1.567574
    Freq: D, dtype: float64