【问题标题】:pandas reindex with data framepandas 用数据框重新索引
【发布时间】:2014-11-07 02:41:20
【问题描述】:

我有一个具有三个级别的多索引的 DataFrame,例如:

                   COL1  COL2  ...
CHROM  POS  LABEL                 
chr1   43   strA   ...   ...   ...
            strB   ...   ...   ...
       66   strC   ...   ...   ...
            strB   ...   ...   ...
chr2   29   strD   ...   ...   ...
...    ...  ...    ...   ...   ...

还有一个带有多索引的系列,其中前两个级别的 DataFrame 索引:

            VAL
CHROM  POS     
chr1   43   v1
       66   v2
chr2   29   v3
...    ...  ...

我想在 DataFrame 中添加一个带有 Series 的列,为前两个级别匹配的每个索引重复值 v1、v2...,如下所示:

                   COL1  COL2  NEW  ...
CHROM  POS  LABEL                 
chr1   43   strA   ...   ...   v1   ...
            strB   ...   ...   v1   ...
       66   strC   ...   ...   v2   ...
            strB   ...   ...   v2   ...
chr2   29   strD   ...   ...   v3   ...
...    ...  ...    ...   ...   ...  ...

注意Series没有缺失的行,即DataFrame中的所有(CHROM,POS)也在Series中。 我有一个可行的解决方案:

pandas.Series(variant_db.index.map(lambda i: cov_per_sample[sample].loc[i[:2]]), index=variant_db.index)

但是,由于那个 lambda,它对于大数据(数十万行)来说非常慢。 我尝试了更快:

df['NEW'] = s.reindex(df.index, method='ffill')

但是这样在df['NEW']中有很多NaN,这不应该发生。使用 method='bfill' 我在不同的位置得到了 NaN,但是在这两种情况下,有些行都得到了 NaN,所以即使使用两者也不起作用。

为了提高效率,我想要一种仅使用库函数的方法。 有人可以帮忙吗?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以使用大数据尝试这个非常简单的解决方案以提高性能:

    df1=pandas.DataFrame([
    {'CHROM':'chr1','POS':43,'LABEL':'strA'},
    {'CHROM':'chr1','POS':43,'LABEL':'strB'},
    {'CHROM':'chr1','POS':66,'LABEL':'strC'},
    {'CHROM':'chr1','POS':66,'LABEL':'strB'},
    {'CHROM':'chr2','POS':29,'LABEL':'strD'}])
    
    df2=pandas.DataFrame([
    {'CHROM':'chr1','POS':43,'VAL':'v1'},
    {'CHROM':'chr1','POS':66,'VAL':'v2'},
    {'CHROM':'chr2','POS':29,'VAL':'v3'}])
    
    for i,r in df2.iterrows():
        df1.ix[(df1['CHROM']==r['CHROM']) & (df1['POS']==r['POS']),'NEW']=r['VAL']
    

    或者使用索引:

    df1=pandas.DataFrame([
    {'CHROM':'chr1','POS':43,'LABEL':'strA','COL':''},
    {'CHROM':'chr1','POS':43,'LABEL':'strB','COL':''},
    {'CHROM':'chr1','POS':66,'LABEL':'strC','COL':''},
    {'CHROM':'chr1','POS':66,'LABEL':'strB','COL':''},
    {'CHROM':'chr2','POS':29,'LABEL':'strD','COL':''}]).set_index(['CHROM','POS','LABEL'])
    
    df2=pandas.DataFrame([
    {'CHROM':'chr1','POS':43,'VAL':'v1'},
    {'CHROM':'chr1','POS':66,'VAL':'v2'},
    {'CHROM':'chr2','POS':29,'VAL':'v3'}]).set_index(['CHROM','POS'])
    
    for i,r in df2.iterrows():
        df1.ix[(i[0],i[1]),'NEW']=r['VAL']
    

    【讨论】:

      【解决方案2】:

      这就是熊猫的全部意义所在。使用索引对您有利。

      df1 = df1.reset_index().set_index(['CHROM', 'POS'])
      df1['NEW'] = df2.VAL
      

      【讨论】:

        【解决方案3】:

        详细说明@acushner 提供的答案,这样的事情应该可以工作

        midx = pd.MultiIndex.from_product(
            [["chr1","chr2"],[43,66,29],["strA","strB","strC"]],
            names=["CHROM", "POS", "LABEL"]
            )
        
        df = pd.DataFrame(random.random([18,2]), index=midx)
        
        midx2 = pd.MultiIndex.from_product([["chr1","chr2"],[43,66,29]],
                                           names=["CHROM", "POS"])
        ser = pd.Series(random.random(6), index=midx2)
        
        df = df.reset_index().set_index(['CHROM', 'POS'])
        df[2] = ser
        df.set_index("LABEL", append=True, inplace=True)
        

        【讨论】:

          猜你喜欢
          • 2019-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-05
          • 2020-04-16
          • 2020-07-22
          • 2020-10-22
          相关资源
          最近更新 更多