【Pandas】列方向にデータを追加する方法[Python]

  • URLをコピーしました!
目次

Pandas

前回、Pandasで行方向にデータを追加する方法を紹介しました。

今回はPandasで列方向にデータを追加する方法を紹介します。

それでは始めていきましょう。

df[列名]でデータを追加

データフレームに列としてデータを追加する方法としては「df[列名]」でデータを追加する方法があります。

辞書の様に追加できることから簡単に使える方法です。

import pandas as pd
import numpy as np

column_num = 10

df = pd.DataFrame()

rng = np.random.default_rng()

for c_num in range(column_num):
    df[c_num] = rng.random(10)
    
print(df)

実行結果
          0         1         2         3         4         5         6  \
0  0.092656  0.588085  0.532506  0.620316  0.746281  0.901826  0.545977   
1  0.249781  0.452919  0.896740  0.204829  0.795558  0.912468  0.218823   
2  0.944426  0.131438  0.094824  0.322589  0.834228  0.689732  0.730281   
3  0.014335  0.750955  0.810115  0.174651  0.229884  0.236513  0.527441   
4  0.189177  0.806379  0.416009  0.006121  0.729997  0.497447  0.846570   
5  0.828416  0.219259  0.500104  0.777865  0.523318  0.471064  0.403795   
6  0.447570  0.684697  0.773767  0.030717  0.982740  0.672824  0.295245   
7  0.654365  0.677355  0.067456  0.132455  0.221908  0.638855  0.197908   
8  0.913537  0.822408  0.069830  0.205479  0.446807  0.599840  0.611137   
9  0.225850  0.055669  0.051397  0.863112  0.408996  0.892111  0.916572   

          7         8         9  
0  0.046294  0.908354  0.442617  
1  0.763491  0.751801  0.457829  
2  0.835838  0.370997  0.630565  
3  0.082151  0.835465  0.621463  
4  0.440525  0.337358  0.508486  
5  0.161462  0.401410  0.112175  
6  0.239742  0.712198  0.131989  
7  0.770848  0.707108  0.046263  
8  0.881027  0.071912  0.824282  
9  0.290916  0.062953  0.304602  

データはNumPyの乱数ジェネレータを使って作成しています。

NumPyの乱数ジェネレータに関してはこちらの記事で紹介していますので、よかったらどうぞ。

この方法は気軽に使える反面、データが多くなると警告が表示されます。

import pandas as pd
import numpy as np

column_num = 1000

df = pd.DataFrame()

rng = np.random.default_rng()

for c_num in range(column_num):
    df[c_num] = rng.random(10)
    
print(df)

実行結果
        0         1         2         3         4         5         6    \
0  0.733494  0.629504  0.509985  0.825894  0.918788  0.550446  0.084953   
1  0.760066  0.849370  0.062400  0.060143  0.805701  0.553981  0.280778   
2  0.961861  0.400218  0.857443  0.422398  0.208799  0.095947  0.596483   
3  0.195917  0.340802  0.054104  0.147578  0.857959  0.935003  0.177356   
4  0.361968  0.459286  0.266768  0.819802  0.647429  0.886624  0.108233   
5  0.126987  0.947966  0.041688  0.495567  0.943472  0.507224  0.003541   
6  0.261173  0.586281  0.538216  0.315045  0.792654  0.259711  0.907976   
7  0.208204  0.228209  0.276961  0.065344  0.797434  0.954079  0.688665   
8  0.603933  0.050230  0.967057  0.385749  0.510954  0.113342  0.252529   
9  0.182743  0.380019  0.273160  0.060995  0.949326  0.223114  0.536474   

        7         8         9    ...       990       991       992       993  \
0  0.883164  0.709349  0.183049  ...  0.933866  0.040979  0.975156  0.464766   
1  0.849817  0.429039  0.003395  ...  0.024883  0.596757  0.115032  0.541966   
2  0.863383  0.092015  0.535166  ...  0.011203  0.202082  0.003687  0.207222   
3  0.742999  0.123932  0.083437  ...  0.443101  0.087289  0.965444  0.457584   
4  0.586670  0.103896  0.303144  ...  0.336918  0.717651  0.292918  0.106690   
5  0.538667  0.960127  0.029582  ...  0.720822  0.655445  0.685659  0.575143   
6  0.351879  0.289922  0.201163  ...  0.644014  0.115342  0.817834  0.518394   
7  0.713238  0.525287  0.423531  ...  0.390353  0.452647  0.392868  0.802239   
8  0.974515  0.962060  0.314861  ...  0.307875  0.709946  0.889314  0.643739   
9  0.331779  0.706041  0.360907  ...  0.234418  0.102739  0.276772  0.435830   

        994       995       996       997       998       999  
0  0.807274  0.644940  0.542253  0.078494  0.536312  0.456097  
1  0.101826  0.940361  0.277023  0.458885  0.844071  0.709311  
2  0.791395  0.287934  0.267872  0.755436  0.857506  0.142931  
3  0.816948  0.013948  0.474316  0.425016  0.096720  0.710496  
4  0.216597  0.812262  0.038335  0.895418  0.449557  0.218864  
5  0.060690  0.813329  0.617684  0.041414  0.090541  0.911312  
6  0.649904  0.335219  0.862966  0.200078  0.580466  0.295298  
7  0.224957  0.245704  0.148834  0.321497  0.322426  0.038557  
8  0.891455  0.508967  0.581011  0.696066  0.041718  0.668692  
9  0.934877  0.248474  0.477411  0.304963  0.228504  0.957152  

[10 rows x 1000 columns]
/var/folders/sp/hg7p80kx22s7vct7yb0zl5cm0000gn/T/ipykernel_13283/
4074519197.py:11: PerformanceWarning: DataFrame is highly fragmented.  
This is usually the result of calling `frame.insert` many times, 
which has poor performance.  Consider joining all columns at once 
using pd.concat(axis=1) instead. To get a de-fragmented frame, 
use `newframe = frame.copy()`
  df[c_num] = rng.random(10)

どうやらこの方法はあまりパフォーマンス的に良い方法ではないとのことで、代わりに「pd.concat(axis=1)」を勧められます。

ということで試してみます。

import pandas as pd
import numpy as np

column_num = 1000

df = pd.DataFrame()

rng = np.random.default_rng()

for c_num in range(column_num):
    df_add = pd.DataFrame(rng.random(10), columns=[c_num])
    df = pd.concat([df, df_add], axis=1)
    
print(df)

実行結果
        0         1         2         3         4         5         6    \
0  0.786263  0.340479  0.992491  0.747589  0.434493  0.771517  0.453220   
1  0.885337  0.268389  0.314073  0.234762  0.330169  0.416728  0.973739   
2  0.361635  0.017073  0.998744  0.056415  0.532284  0.870129  0.653355   
3  0.574577  0.322628  0.769415  0.718639  0.514957  0.472393  0.424075   
4  0.300638  0.796059  0.427357  0.817731  0.033193  0.378891  0.127753   
5  0.926530  0.051283  0.587905  0.087341  0.191238  0.527160  0.141225   
6  0.976033  0.437607  0.730176  0.197983  0.802466  0.266694  0.409749   
7  0.587569  0.530384  0.919754  0.679826  0.038273  0.480210  0.239273   
8  0.686917  0.356358  0.570043  0.712713  0.029657  0.281358  0.971709   
9  0.353700  0.225141  0.183434  0.587338  0.826032  0.202260  0.630070   

        7         8         9    ...       990       991       992       993  \
0  0.331685  0.892849  0.585956  ...  0.328649  0.197003  0.940035  0.478013   
1  0.303131  0.113920  0.184395  ...  0.795621  0.816141  0.489325  0.112984   
2  0.665722  0.286215  0.461396  ...  0.966153  0.200030  0.772767  0.611956   
3  0.503761  0.929764  0.288608  ...  0.827622  0.206803  0.694326  0.544831   
4  0.867214  0.835498  0.060055  ...  0.625875  0.617611  0.880740  0.086261   
5  0.824891  0.164958  0.513704  ...  0.872523  0.065001  0.804279  0.023696   
6  0.427018  0.422756  0.550454  ...  0.623516  0.751547  0.354685  0.234894   
7  0.950831  0.520808  0.595640  ...  0.523113  0.397560  0.436270  0.324722   
8  0.415023  0.514080  0.127320  ...  0.715707  0.203550  0.213739  0.145915   
9  0.463468  0.551637  0.051414  ...  0.750758  0.673031  0.840803  0.953849   

        994       995       996       997       998       999  
0  0.636352  0.676099  0.129913  0.990963  0.440906  0.254350  
1  0.571050  0.637301  0.182800  0.761227  0.887743  0.178316  
2  0.500451  0.912980  0.231769  0.819632  0.656509  0.463165  
3  0.732940  0.365772  0.721172  0.793519  0.962898  0.750543  
4  0.106167  0.523814  0.814335  0.670908  0.916438  0.705283  
5  0.888895  0.263819  0.416420  0.239587  0.514156  0.780250  
6  0.823298  0.133149  0.958439  0.329760  0.573206  0.005511  
7  0.034202  0.773206  0.936291  0.308396  0.370357  0.686141  
8  0.605946  0.029003  0.686984  0.744579  0.700958  0.577575  
9  0.022187  0.626076  0.002610  0.935992  0.077373  0.148206  

[10 rows x 1000 columns]

無事追加できました。

辞書を作成してからデータフレームに変換

「pd.concat()」で追加できるのは分かったのですが、これまでの「df[列名]」に比べると追加の方法が複雑で覚えにくいです。

そんな時はいきなりデータフレームを作成してデータを追加していくのではなく、一旦辞書を作成し、データを追加、最後にその辞書をデータフレームへ変換してしまう方法の方が分かりやすいです。

つまりこんな感じです。

import pandas as pd
import numpy as np

column_num = 1000

rng = np.random.default_rng()

data_dic = {}
for c_num in range(column_num):
    data_dic[c_num] = rng.random(10)
    
df = pd.DataFrame(data_dic)
    
print(df)

実行結果
        0         1         2         3         4         5         6    \
0  0.950443  0.510381  0.380969  0.186369  0.205019  0.311203  0.953946   
1  0.449400  0.478602  0.212552  0.943630  0.890136  0.534205  0.581683   
2  0.882497  0.613497  0.786964  0.026933  0.369672  0.974456  0.198081   
3  0.017958  0.225856  0.665516  0.481735  0.045476  0.301894  0.946426   
4  0.757976  0.582993  0.688813  0.689700  0.829662  0.762571  0.730270   
5  0.704493  0.291093  0.692176  0.922951  0.726470  0.109277  0.409830   
6  0.841655  0.083388  0.845499  0.428125  0.250047  0.208356  0.076435   
7  0.645744  0.087695  0.909819  0.006695  0.253948  0.258853  0.104530   
8  0.851999  0.736562  0.567915  0.559663  0.954158  0.244089  0.720233   
9  0.157651  0.172517  0.758822  0.297292  0.691787  0.672509  0.292546   

        7         8         9    ...       990       991       992       993  \
0  0.042144  0.920046  0.066642  ...  0.485595  0.313384  0.201674  0.080643   
1  0.544037  0.115706  0.609323  ...  0.594952  0.023881  0.940372  0.292379   
2  0.034513  0.780951  0.690990  ...  0.580228  0.920914  0.015200  0.789194   
3  0.938626  0.211889  0.146446  ...  0.248981  0.483250  0.645695  0.411195   
4  0.539950  0.535007  0.492523  ...  0.080248  0.177837  0.335017  0.481670   
5  0.347672  0.193756  0.862501  ...  0.992088  0.068966  0.709499  0.462312   
6  0.193551  0.625353  0.813343  ...  0.743419  0.178910  0.883817  0.164956   
7  0.151856  0.500251  0.931229  ...  0.717289  0.105110  0.593391  0.996897   
8  0.592530  0.979624  0.278176  ...  0.226373  0.014485  0.345073  0.601564   
9  0.963083  0.572512  0.850270  ...  0.317426  0.946826  0.335413  0.680110   

        994       995       996       997       998       999  
0  0.717807  0.547350  0.332791  0.020598  0.628083  0.516784  
1  0.035564  0.705203  0.051547  0.688690  0.263680  0.119006  
2  0.151079  0.957535  0.741834  0.156663  0.332617  0.756040  
3  0.144769  0.372371  0.144077  0.554499  0.381099  0.409673  
4  0.048370  0.412778  0.686117  0.544331  0.554991  0.603065  
5  0.680707  0.386414  0.255685  0.272824  0.348710  0.883415  
6  0.230230  0.110729  0.131618  0.810427  0.454233  0.559577  
7  0.187140  0.898828  0.757570  0.071891  0.098087  0.051177  
8  0.988727  0.580772  0.982452  0.384399  0.377691  0.945710  
9  0.130793  0.689802  0.638921  0.902125  0.649613  0.218007  

[10 rows x 1000 columns]

実行速度を比較してみた

パフォーマンスうんぬんという話が出てきたのでJupyter notebookのマジックコマンド「%%timeit」を使って実行速度を比較してみましょう。

ちなみに最後のデータフレームの出力は省略しておきます。

まずは「df[列名]」でデータを追加する方法です。

%%timeit

import pandas as pd
import numpy as np

column_num = 1000

df = pd.DataFrame()

rng = np.random.default_rng()

for c_num in range(column_num):
    df[c_num] = rng.random(10)

実行結果
<magic-timeit>:11: PerformanceWarning: DataFrame is highly 
fragmented.  This is usually the result of calling `frame.insert` 
many times, which has poor performance.  Consider joining all 
columns at once using pd.concat(axis=1) instead. To get a 
de-fragmented frame, use `newframe = frame.copy()`
(中略)
296 ms ± 65.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

次に「pd.concat()」を使う方法です。

%%timeit

import pandas as pd
import numpy as np

column_num = 1000

df = pd.DataFrame()

rng = np.random.default_rng()

for c_num in range(column_num):
    df_add = pd.DataFrame(rng.random(10), columns=[c_num])
    df = pd.concat([df, df_add], axis=1)

実行結果
1.86 s ± 46.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

最後に辞書からデータフレームに変換する方法です。

%%timeit

import pandas as pd
import numpy as np

column_num = 1000

rng = np.random.default_rng()

data_dic = {}
for c_num in range(column_num):
    data_dic[c_num] = rng.random(10)
    
df = pd.DataFrame(data_dic)

実行結果
10.3 ms ± 98.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

「df[列名]」が296ミリ秒、「pd.concat()」が1.86秒、辞書からデータフレームに変換する方法が10.3ミリ秒ということで、圧倒的に辞書からデータフレームに変換する方法が速かったです。

驚いたのは「df[列名]」の代替案として示された「pd.concat()」が圧倒的に遅かったことです。

どうやら警告メッセージ「Consider joining all columns at once using pd.concat(axis=1) instead.」に書かれている中で「at once(同時に)」が重要なのであって「pd.concat()」が重要なのではないと思われます。

そのため最後の辞書からデータフレームに変換する方法、つまり「at once」の方法が圧倒的に速かったのではないでしょうか。

ということでできる限り辞書等でデータをまとめ、データフレームに変換するという方法を取るのが良さそうです。

次回はPandasのデータフレーム内の行列のデータ、もしくはデータフレームをリストに変換する方法を紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次