pandas reindex与数据框架

时间:2014-11-04 17:45:21

标签: python pandas

我有一个带有三个级别的multiindex的DataFrame,例如:

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

和具有带有前两个DataFrame索引级别的multiindex的系列:

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

我想将一个包含Series的列添加到DataFrame中,为前两个级别匹配的每个索引重复值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)也在系列中。 我有一个有效的解决方案:

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,因此即使使用两者也行不通。

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

3 个答案:

答案 0 :(得分:0)

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

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']

答案 1 :(得分:0)

这就是大熊猫的全部意义所在。使用指数对你有利。

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

答案 2 :(得分:0)

详细阐述@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)