2

現在、次のような pandas DataFrame があります。

 ID                    A1      A2       A3       B1       B2       B3
 Ku8QhfS0n_hIOABXuE    6.343   6.304    6.410    6.287    6.403    6.279
 fqPEquJRRlSVSfL.8A    6.752   6.681    6.680    6.677    6.525    6.739
 ckiehnugOno9d7vf1Q    6.297   6.248    6.524    6.382    6.316    6.453
 x57Vw5B5Fbt5JUnQkI    6.268   6.451    6.379    6.371    6.458    6.333

この DataFrame は、順列テストを必要とする統計と共に使用されます (編集: 正確には、ランダム順列)。各列のインデックスは、100 回シャッフル (サンプリング) する必要があります。サイズの目安として、行数は約 50,000 になります。

編集: 順列は行に沿っています。つまり、各列のインデックスをシャッフルします。

ここでの最大の問題は、パフォーマンスの 1 つです。物事をすばやく並べ替えたい。

私が考えていた例は次のとおりです。

import random
import joblib

def permutation(dataframe):
    return dataframe.apply(random.sample, axis=1, k=len(dataframe))

permute = joblib.delayed(permutation)
pool = joblib.Parallel(n_jobs=-2) # all cores minus 1
result = pool(permute(dataframe) for item in range(100))

ここでの問題は、これを行うとテストが安定しないことです。明らかに順列は機能しますが、並列で実行しない場合ほど「ランダム」ではないため、使用すると結果の安定性が失われますフォローアップ計算で並べ替えられたデータ。

したがって、私の唯一の「解決策」は、並列コードを実行する前にすべての列のすべてのインデックスを事前に計算することでした。これにより、処理が大幅に遅くなります。

私の質問は次のとおりです。

  1. この順列を行うためのより効率的な方法はありますか? (平行とは限りません)
  2. 並列アプローチ (スレッドではなく複数のプロセスを使用) は実現可能ですか?

編集:物事をより明確にするために、たとえば1回のシャッフル後に列A1に何が起こるべきかを次に示します。

Ku8QhfS0n_hIOABXuE    6.268   
fqPEquJRRlSVSfL.8A    6.343
ckiehnugOno9d7vf1Q    6.752
x57Vw5B5Fbt5JUnQk     6.297

(つまり、行の値が移動していました)。

EDIT2:これが私が今使っているものです:

def _generate_indices(indices, columns, nperm):

    random.seed(1234567890)
    num_genes = indices.size

    for item in range(nperm):

        permuted = pandas.DataFrame(
            {column: random.sample(genes, num_genes) for column in columns},
             index=range(genes.size)
        )

        yield permuted

(要するに、各列のリサンプリングされたインデックスの DataFrame を構築します)

そして後で(はい、私はそれがかなり醜いことを知っています):

 # Data is the original DataFrame
 # Indices one of the results of that generator

 permuted = dict()

 for column in data.columns:

    value = data[column]
    permuted[column] = value[indices[column].values].values

 permuted_table = pandas.DataFrame(permuted, index=data.index)
4

1 に答える 1

1

これはどう:

In [1]: import numpy as np; import pandas as pd

In [2]: df = pd.DataFrame(np.random.randn(50000, 10))

In [3]: def shuffle(df, n):
   ....:     for i in n:
   ....:         np.random.shuffle(df.values)
   ....:     return df


In [4]: df.head()
Out[4]:
          0         1         2         3         4         5         6         7         8         9
0  0.329588 -0.513814 -1.267923  0.691889 -0.319635 -1.468145 -0.441789  0.004142 -0.362073 -0.555779
1  0.495670  2.460727  1.174324  1.115692  1.214057 -0.843138  0.217075  0.495385  1.568166  0.252299
2 -0.898075  0.994281 -0.281349 -0.104684 -1.686646  0.651502 -1.466679 -1.256705  1.354484  0.626840
3  1.158388 -1.227794 -0.462005 -1.790205  0.399956 -1.631035 -1.707944 -1.126572 -0.892759  1.396455
4 -0.049915  0.006599 -1.099983  0.775028 -0.694906 -1.376802 -0.152225  1.413212  0.050213 -0.209760

In [5]: shuffle(df, 1).head(5)
Out[5]:
          0         1         2         3         4         5         6         7         8         9
0  2.044131  0.072214 -0.304449  0.201148  1.462055  0.538476 -0.059249 -0.133299  2.925301  0.529678
1  0.036957  0.214003 -1.042905 -0.029864  1.616543  0.840719  0.104798 -0.766586 -0.723782 -0.088239
2 -0.025621  0.657951  1.132175 -0.815403  0.548210 -0.029291  0.575587  0.032481 -0.261873  0.010381
3  1.396024  0.859455 -1.514801  0.353378  1.790324  0.286164 -0.765518  1.363027 -0.868599 -0.082818
4 -0.026649 -0.090119 -2.289810 -0.701342 -0.116262 -0.674597 -0.580760 -0.895089 -0.663331  0.

In [6]: %timeit shuffle(df, 100)
Out[6]:
1 loops, best of 3: 14.4 s per loop

これは、必要なことを行います。唯一の問題は、それが十分に速いかどうかです。

アップデート

@Einar のコメントに従って、ソリューションを変更しました。

In[7]: def shuffle2(df, n):
           ind = df.index
           for i in range(n):
               sampler = np.random.permutation(df.shape[0])
               new_vals = df.take(sampler).values
               df = pd.DataFrame(new_vals, index=ind)
           return df

In [8]: df.head()
Out[8]: 
          0         1         2         3         4         5         6         7         8         9
0 -0.175006 -0.462306  0.565517 -0.309398  1.100570  0.656627  1.207535 -0.221079 -0.933068 -0.192759
1  0.388165  0.155480 -0.015188  0.868497  1.102662 -0.571818 -0.994005  0.600943  2.205520 -0.294121
2  0.281605 -1.637529  2.238149  0.987409 -1.979691 -0.040130  1.121140  1.190092 -0.118919  0.790367
3  1.054509  0.395444  1.239756 -0.439000  0.146727 -1.705972  0.627053 -0.547096 -0.818094 -0.056983
4  0.209031 -0.233167 -1.900261 -0.678022 -0.064092 -1.562976 -1.516468  0.512461  1.058758 -0.206019

In [9]: shuffle2(df, 1).head()
Out[9]: 
          0         1         2         3         4         5         6         7         8         9
0  0.054355  0.129432 -0.805284 -1.713622 -0.610555 -0.874039 -0.840880  0.593901  0.182513 -1.981521
1  0.624562  1.097495 -0.428710 -0.133220  0.675428  0.892044  0.752593 -0.702470  0.272386 -0.193440
2  0.763551 -0.505923  0.206675  0.561456  0.441514 -0.743498 -1.462773 -0.061210 -0.435449 -2.677681
3  1.149586 -0.003552  2.496176 -0.089767  0.246546 -1.333184  0.524872 -0.527519  0.492978 -0.829365
4 -1.893188  0.728737  0.361983 -0.188709 -0.809291  2.093554  0.396242  0.402482  1.884082  1.373781

In [10]: timeit shuffle2(df, 100)
1 loops, best of 3: 2.47 s per loop
于 2012-11-15T16:17:23.213 に答える