データフレームで行をx回複製する-パフォーマンスを向上させる[複製]

Aug 24 2020

データフレーム行を複製するための最も効率的なソリューションを探しています。各行はx回複製する必要があります。ここで、xは各行で一意です。

これが私の与えられたデータフレームであるとしましょう:

| id | count |
|----|-------|
| a  | 1     |
| b  | 2     |
| c  | 5     |

結果として、データフレームは次のようになります。各行は、列「count」で指定された量だけ複製されました。

| id | count |
|----|-------|
| a  | 1     |
| b  | 2     |
| b  | 2     |
| c  | 5     |
| c  | 5     |
| c  | 5     |
| c  | 5     |
| c  | 5     |

非常に基本的なアプローチは、データフレームをループし、次のように行をx回追加することです。

data = {'id': ['a', 'b', 'c'], 'count': [1, 2, 5]}
df = pd.DataFrame(data=data)

for index, row in df.iterrows():
    for x in range(row['count']-1):
        df = df.append(pd.Series(row, index=df.columns), ignore_index=True)

df = df.sort_values(by=['id'])
df = df.reset_index(drop=True)

df

これは小さなデータフレームでは機能しますが、数千行の大きなデータフレームではあまり効率的ではありません。各行は最大200回複製する必要があるため、最終的なデータフレームには数百万行を含めることができます。

すでにパンダ/ numpyのベクトル化について読んでいますが、残念ながら、データフレームに多くの行を追加する必要があるこの場合に役立つかどうか(およびどのように役立つか)はわかりません。

パフォーマンスを改善する方法について何か提案はありますか?

回答

4 jezrael Aug 24 2020 at 20:10

Index.repeat一意のインデックス値の場合に使用してから、DataFrame.loc:に渡します。

df1 = df.loc[df.index.repeat(df['count'])].reset_index(drop=True)
print (df1)
  id  count
0  a      1
1  b      2
2  b      2
3  c      5
4  c      5
5  c      5
6  c      5
7  c      5

可能であれば、インデックス値のいくつかの重複が可能使用であるnumpy.repeatとDataFrame.iloc:

print (df)
  id  count
0  a      1
1  b      2
1  c      5

df1 = df.iloc[np.repeat(np.arange(len(df.index)), df['count'])].reset_index(drop=True)
print (df1)
  id  count
0  a      1
1  b      2
2  b      2
3  c      5
4  c      5
5  c      5
6  c      5
7  c      5
1 sammywemmy Aug 24 2020 at 20:14

次のcount列を使用してインデックスを再作成できます。

df.reindex(df.index.repeat(df["count"])).reset_index(drop=True)
DarshShukla Aug 24 2020 at 21:49
In [1]: import numpy as np 
   ...: import pandas as pd                                                                         

In [2]: data = {'id':list(map(chr, range(97, 123))), 'count': pd.Series(np.random.randint(0,500,size
   ...: =26))}                                                                                      

In [3]: df = pd.DataFrame(data)                                                                     

In [4]: df.head()                                                                                   
Out[4]: 
  id  count
0  a    145
1  b    297
2  c     46
3  d    493
4  e     46

In [5]: df_replicate = pd.DataFrame(np.repeat(df.values, df['count'], axis=0),columns=df.columns)   

In [6]: df_replicate.head()                                                                         
Out[6]: 
  id count
0  a   145
1  a   145
2  a   145
3  a   145
4  a   145