2017-07-20 11 views
1

のために一度に複数の列の内容を置き換える:パンダは、次のように私がDFを持っている複数の条件

CHROM  POS SRR4216489    SRR4216675     SRR4216480 
0  1 127536  ./.      ./.       ./. 
1  1 127573  ./.      0/1:0,5:5:0:112,1,10  ./. 
2  1 135032  ./.      1/1:13,0:13:3240:0,30,361 0/0:13,0:13:3240:0,30,361 
3  1 135208  ./.      0/0:5,0:5:3240:0,20,160  0/1:5,0:5:3240:0,20,160 
4  1 138558  1/1:5,0:5:3240:0,29,177 0/0:0,5:5:0:112,1,10  ./. 

私は特定の条件に応じて、サンプル列の内容を交換したいと思います。サンプル列は、SRR4216489、SRR4216675、SRR4216480です。私は './'を置き換えることを望んでいます。 0.5で始まり、0/0のものは0.0で、何も0/1や1/1で1.0です。私はそれがいくつかのプロセスに関係することを感謝します。そのほとんどは私が独立して行うことができますが、それらを結びつける構文はわかりません。例えば、私はサンプルSRR4216480のためにこれを行うことができます:

df['SRR4216675'][df.SRR4216675 == './.'] = 0.5 

これがうまく機能し、courtesy of hereが、私は同時にサンプル列のすべてにそれを適用するかどうかはわかりません。私はでループを使用することを考えた:

sample_cols = df.columns[2:] 
for s in sample_cols: 
    df[s][df.s =='./.'] = 0.5 

が、これはまず非常にpandonicいないようだと、それはまた、とにかく「df.s」でのリストから文字列を受け付けません。

次の課題は、サンプル列の他の部分を埋める変数文字列を解析する方法です。私は、スプリット機能を使って試してみました:

df=df['SRR4216675'][df.SRR4216675.split(':') == '0/0' ] = 0.0 

が、私は得る:

TypeError: 'float' object is not subscriptable 

私はこの問題を解決する良い方法は、このようなthisとしてラムダを使用しますがパンダに新しいものであろうと確信しているとそのほとんどがのように見えますが、値を置き換えるためにさらに処理が必要であり、それが2列に持っているようにも見えますが、それ

col=df['SRR4216675'][df.SRR4216675.apply(lambda x: x.split(':')[0])] 

:ラムダ私はそれは難しい見つけるよ、私はここに着いdは文句を言わない私は、既存のDFにそれを再統合してみましょう:

SRR4216675 
./. NaN 
0/1 NaN 
1/1 NaN 
0/0 NaN 
0/0 NaN 

df['SRR4216675'] = col 

ValueError: cannot reindex from a duplicate axis 

私は、これが1でいくつかの問題ですが、私はパンダに新しいですし、本当にそれでグリップを得るしたいことを理解します。私はこれらの問題をPythonsの標準リスト、繰り返し、文字列解析関数で基本リストとループを使って解決することができましたが、フルサイズのdfが何百万行にもなり、500個以上のサンプル列を含むので、

+0

はパンダシリーズと 'pd.Series.replace()'メソッドへの様々な '.str'方法を調べてください。例: 'df.loc [:, 'SRR4216689'、 'SRR4216675'、 'SRR4216480']。replace(" ./。0.5、inplace = True) ' – Jakub

答えて

1

あなたはこのように、df.applyを使用して関数を定義することによってこれを行うことができます。

In [10]: cols = ('SRR4216675', 'SRR4216480', 'SRR4216489') 

In [11]: def replace_vals(row): 
    ...:  for col in cols: 
    ...:   if row[col] == './.': 
    ...:    row[col] = 0.5 
    ...:   elif row[col].startswith('0/0'): 
    ...:    row[col] = 0 
    ...:   elif row[col].startswith('0/1') or row[col].startswith('1/1'): 
    ...:    row[col] = 1 
    ...:  return row 
    ...: 
    ...: 

In [12]: df.apply(replace_vals, axis=1) 
Out[12]: 
    CHROM  POS SRR4216480 SRR4216489 SRR4216675 
0  1 127536   0.5   0.5   0.5 
1  1 127573   0.5   0.5   1.0 
2  1 135032   0.0   0.5   1.0 
3  1 135208   1.0   0.5   0.0 
4  1 138558   0.5   1.0   0.0 

そして、ここではこれを行うにはより高速な方法です:

まずは、とても大きなデータフレームを作成してみましょう意味のある時間差を測ることができ、測定できるようにタイマーをインポートしましょう。我々は上記定義した関数を使用して

In [70]: from timeit import default_timer as timer 

In [71]: long_df = pd.DataFrame() 

In [72]: for i in range(10000): 
    ...:  long_df = pd.concat([long_df, df]) 

、我々が得る:

In [76]: start = timer(); long_df.apply(replace_vals, axis=1); end = timer() 

In [77]: end - start 
Out[77]: 8.662535898998613 

を、私たちはどこの列の上に私たちのループ(簡単にタイミングの目的のために)新しい関数を定義し、同じ交換を適用しますロジックは、上記のように、私たちはそれぞれの列にベクトル化str.startswithメソッドを使用して、それを行う以外:

In [78]: def modify_vectorized(): 
    ...:  start = timer() 
    ...:  for col in cols: 
    ...:   long_df.loc[long_df[col] == './.', col] = 0.5 
    ...:   long_df.loc[long_df[col].str.startswith('0/0', na=False), col] = 0 
    ...:   long_df.loc[long_df[col].str.startswith('0/1', na=False), col] = 1 
    ...:   long_df.loc[long_df[col].str.startswith('1/1', na=False), col] = 1 
    ...:  end = timer() 
    ...:  return end - start 

我々は大規模なデータフレームを再作成し、我々はそれに新しい機能を実行し、取得します大幅な高速化:

In [79]: long_df = pd.DataFrame() 

In [80]: for i in range(10000): 
    ...:  long_df = pd.concat([long_df, df]) 
    ...: 

In [81]: time_elapsed = modify_vectorized() 

In [82]: time_elapsed 
Out[82]: 0.44004046998452395 

結果のデータフレームは、次のようになります。

In [83]: long_df 
Out[83]: 
    CHROM  POS SRR4216480 SRR4216489 SRR4216675 
0  1 127536  0.5  0.5  0.5 
1  1 127573  0.5  0.5   1 
2  1 135032   0  0.5   1 
3  1 135208   1  0.5   0 
4  1 138558  0.5   1   0 
0  1 127536  0.5  0.5  0.5 
1  1 127573  0.5  0.5   1 
2  1 135032   0  0.5   1 
3  1 135208   1  0.5   0 
4  1 138558  0.5   1   0 
0  1 127536  0.5  0.5  0.5 
1  1 127573  0.5  0.5   1 
2  1 135032   0  0.5   1 
3  1 135208   1  0.5   0 
4  1 138558  0.5   1   0 
0  1 127536  0.5  0.5  0.5 
... 
+0

ありがとうございます。しかし、列に?関数に列の引数を追加しようとすると、関数が呼び出されないときに関数に引数を渡します。 – user3062260

+0

私の答えを更新して、より一般的な変更を加える列を作成しました。 – LateCoder

+0

ありがとうございました!このソリューションは機能しますが、スピードアップするためのさらなる提案は必須ではありませんが、すばらしいことになります。 1つの染色体を走らせるのに約5分かかりましたが、私はそれを存続させることができます(それを実行する24の染色体があります)。再度、感謝します! – user3062260

関連する問題