その1:質問のコードを直したもの
python
1df["ID"] = df['Season'].astype(str).str.cat([
2 df[['WTeamID', 'LTeamID']].min(1).astype(str),
3 df[['WTeamID', 'LTeamID']].max(1).astype(str)], '_')
その2:より簡単なコード
python
1df["ID"] = df['Season'].astype(str).str.cat(
2 np.sort(df[['LTeamID', 'WTeamID']].to_numpy()).astype(str), '_')
その3:リストを使う方法
python
1arr_s = df['Season'].tolist()
2arr_lw = np.sort(df[['LTeamID', 'WTeamID']].to_numpy()).tolist()
3df["ID"] = pd.Series([f'{s}_{lw[0]}_{lw[1]}' for s, lw in zip(arr_s, arr_lw)],
4 index=df.index)
解説(その1)
①str(df["Season"]) のoutputがdataframe形式で返されない
str()
は文字列型を返す関数です。pd.Series
(或いはpd.DataFrame
)のデータ型を文字列型(正確にはオブジェクト型)にする場合はpd.Series.astype(str)
を使います。
python
1In [22]: df['Season']
2Out[22]:
31916 2015
41917 2015
51918 2015
61919 2015
71920 2015
8... ...
91978 2015
101979 2015
111980 2015
121981 2015
131982 2015
14Name: Season, dtype: int64
15
16In [23]: df['Season'].astype(str)
17Out[23]:
181916 2015
191917 2015
201918 2015
211919 2015
221920 2015
23... ...
241978 2015
251979 2015
261980 2015
271981 2015
281982 2015
29Name: Season, dtype: object
文字列データ型の結合にはpd.Series.str.cat()
を使います。⇒公式ドキュメント
python
1In [24]: df['Season'].astype(str).str.cat(df[['WTeamID', 'LTeamID']].astype(str), '_')
2Out[24]:
31916 2015_1214_1264
41917 2015_1279_1140
51918 2015_1173_1129
61919 2015_1352_1316
71920 2015_1112_1411
8... ...
91978 2015_1181_1211
101979 2015_1277_1257
111980 2015_1181_1277
121981 2015_1458_1246
131982 2015_1181_1458
14Name: Season, dtype: object
②min(df["WTeamID"], df["LTeamID"])、自体がそもそもerrorとなる
min()
は小さい方の数値を返す関数です。pd.Series
(或いはpd.DataFrame
)の最小値を求める場合はpd.Series.min()
を使います。pd.DataFrame
の場合は方向を指定します。
python
1In [25]: df[['WTeamID', 'LTeamID']].min(1)
2Out[25]:
31916 1214
41917 1140
51918 1129
61919 1316
71920 1112
8... ...
91978 1181
101979 1257
111980 1181
121981 1246
131982 1181
14dtype: int64
同様にpd.Series
(或いはpd.DataFrame
)の最大値を求める場合はpd.Series.max()
を使います。
したがって、
python
1In [26]: df['Season'].astype(str).str.cat([
2 2 df[['WTeamID', 'LTeamID']].min(1).astype(str),
3 3 df[['WTeamID', 'LTeamID']].max(1).astype(str)], '_')
4Out[26]:
51916 2015_1214_1264
61917 2015_1140_1279
71918 2015_1129_1173
81919 2015_1316_1352
91920 2015_1112_1411
10... ...
111978 2015_1181_1211
121979 2015_1257_1277
131980 2015_1181_1277
141981 2015_1246_1458
151982 2015_1181_1458
16Name: Season, dtype: object
解説(その2)
今回の場合、数値を比較して「小さい方_大きい方」という部分がありますが、この部分はnp.sort()
を使うって行ごとに「小さい→大きい」順に並べ替えした配列を作るのが簡便です。
つまり、
python
1In [5]: arr = np.sort(df[['LTeamID', 'WTeamID']].to_numpy())
2 2 arr
3Out[5]:
4array([[1214, 1264],
5 [1140, 1279],
6 [1129, 1173],
7 [1316, 1352],
8 [1112, 1411],
9 ... ...
10 [1181, 1211],
11 [1257, 1277],
12 [1181, 1277],
13 [1246, 1458],
14 [1181, 1458]], dtype=int64)
15
16In [6]: df['Season'].astype(str).str.cat(arr.astype(str), '_')
17Out[6]:
181916 2015_1214_1264
191917 2015_1140_1279
201918 2015_1129_1173
211919 2015_1316_1352
221920 2015_1112_1411
23... ...
241978 2015_1181_1211
251979 2015_1257_1277
261980 2015_1181_1277
271981 2015_1246_1458
281982 2015_1181_1458
29Name: Season, dtype: object
解説(その3)
pandasのstr
関連メソッドは実際にはとても動作が遅いです。標準のリストになおしてforループした方が速い場合があります。
python
1In [11]: arr_s = df['Season'].tolist()
2 2 arr_lw = np.sort(df[['LTeamID', 'WTeamID']].to_numpy()).tolist()
3 3 id_list = [f'{s}_{lw[0]}_{lw[1]}' for s, lw in zip(arr_s, arr_lw)]
4 4 id_list
5Out[11]:
6['2015_1214_1264',
7 '2015_1140_1279',
8 '2015_1129_1173',
9 '2015_1316_1352',
10 '2015_1112_1411',
11 '2015_1181_1211',
12 '2015_1257_1277',
13 '2015_1181_1277',
14 '2015_1246_1458',
15 '2015_1181_1458']
16
17In [12]: pd.Series(id_list, index=df.index)
18Out[12]:
191916 2015_1214_1264
201917 2015_1140_1279
211918 2015_1129_1173
221919 2015_1316_1352
231920 2015_1112_1411
241978 2015_1181_1211
251979 2015_1257_1277
261980 2015_1181_1277
271981 2015_1246_1458
281982 2015_1181_1458
29dtype: object
処理速度の比較
その3(リストを使う方法)が最も速いようです。@can110氏の方法(df.apply
を使った方法)はデータ数が少ないときは次いで速いですが、行数が増えるとかなり遅くなります。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/20 09:14