web-dev-qa-db-ja.com

パンダでマルチインデックス付きのマップを使用するにはどうすればよいですか?

さまざまなゲノム位置のデータのデータテーブルがあります。位置は、私が多重指数に変えた3タプル(「染色体」、「srand」、位置)として表されます。私の目標は、各位置に関するさまざまな情報を検索し、それをテーブルに追加することです(たとえば、遺伝子名など)。これはpybedtoolsで実行できます。

df = pd.DataFrame(data={'A':range(1,8), 'B':range(1,8), 'C': range(1,8)},
 index=pd.MultiIndex.from_tuples([('chrom1', '-', 1234), ('chrom1', '+', 5678),
 ('chrom1', '+', 9876),  ('chrom2', '+', 13579), ('chrom2', '+', 8497), ('chrom2', '-', 98765),
 ('chrom2', '-', 76856)]))

df.index.rename(['chrom','strand','abs_pos'], inplace=True)

                       A  B  C
chrom  strand abs_pos         
chrom1 -      1234     1  1  1
       +      5678     2  2  2
              9876     3  3  3
chrom2 +      13579    4  4  4
              8497     5  5  5
       -      98765    6  6  6
              76856    7  7  7

私の問題は、多重指数を使用してデータフレームに列を追加することです。これは、マルチインデックスがなくても簡単に思えます: パンダ-辞書からデータフレームに新しい列を追加します

マルチインデックスに対応する3タプルキーのルックアップ情報の辞書があります。このデータを新しい列として追加するにはどうすればよいですか?

gene_d = {('chrom1', '-', 1234) : 'geneA', ('chrom1', '+', 5678): 'geneB', 
    ('chrom1', '+', 9876): 'geneC', ('chrom2', '+', 13579): 'geneD',
    ('chrom2', '+', 8497): 'geneE', ('chrom2', '-', 98765): 'geneF', 
    ('chrom2', '-', 76856): 'geneG'}

マップを試しましたが、マルチインデックスでマップを機能させて次のようにする方法がわからないようです。

                                A  B  C
chrom  strand abs_pos gene
chrom1 -      1234    geneA     1  1  1
       +      5678    geneB     2  2  2
              9876    geneC     3  3  3
chrom2 +      13579   geneD     4  4  4
              8497    geneE     5  5  5
       -      98765   geneF     6  6  6
              76856   geneG     7  7  7
13
HikerT

ベクトル化されたアプローチ:

df['gene'] = df.index #you get the index as Tuple
df['gene'] = df['gene'].map(gene_d)
df = df.set_index('gene', append=True)

結果のdf:

                                A   B   C
chrom   strand  abs_pos gene            
chrom1  -       1234    geneA   1   1   1
        +       5678    geneB   2   2   2
                9876    geneC   3   3   3
chrom2  +       13579   geneD   4   4   4
                8497    geneE   5   5   5
        -       98765   geneF   6   6   6
                76856   geneG   7   7   7
9
Vaishali

Gene_dをデータフレームにします。

df1 = pd.DataFrame.from_dict(gene_d, orient='index').rename(columns={0:'gene'})

それに多重指数を与える:

df1.index = pd.MultiIndex.from_tuples(df1.index)

元のdfと連結します。

new_df = pd.concat([df, df1], axis=1).sort_values('A')

クリーンアップを行います。

new_df.index.rename(['chrom','strand','abs_pos'], inplace=True)
new_df.set_index('gene', append=True)
new_df

                             A  B  C
chrom  strand abs_pos gene          
chrom1 -      1234    geneA  1  1  1
       +      5678    geneB  2  2  2
              9876    geneC  3  3  3
chrom2 +      13579   geneD  4  4  4
              8497    geneE  5  5  5
       -      98765   geneF  6  6  6
              76856   geneG  7  7  7
2
ChuHo

ベクトル化されていないアプローチですが、これに本当に苦労している人にはおそらく役立つでしょう。

私の例では、bb_dfというdfがあります。これは、構造として[customer、months]を持つmultindexを持ち、各サイトの下に複数の月があります。 multindexは(levels = [level_1、level_2]、labels = [level_1、level_2])のように構成されています。そのため、次のリスト内包表記により、マッピング用にレベル2レベルの完全なリストを順番に取得できます。

[bb_df.index.levels[1][x] for x in bb_df.index.labels[1]]

これが誰かに役立つことを願っています。

0
Chester H

ループを使用すると非常に簡単です。ループする場合は、dictが適切なデータ構造ではない可能性があり、タプルのリストにすぎない可能性があることに注意してください。

In [14]: for k, v in gene_d.items():
    ...:     df.loc[k,'gene'] = v
    ...:

In [15]: df
Out[15]:
                       A  B  C   gene
chrom  strand abs_pos
chrom1 -      1234     1  1  1  geneA
       +      5678     2  2  2  geneB
              9876     3  3  3  geneC
chrom2 +      13579    4  4  4  geneD
              8497     5  5  5  geneE
       -      98765    6  6  6  geneF
              76856    7  7  7  geneG

In [16]:
0