J'ai le tableau pandas suivant
df:
df['new_column'] = df[~df.EVNT_ID].apply(lambda x: '|'.join(x.dropna().astype(str).values), axis=1)
Maintenant, j'essaye de concater toutes les colonnes sauf la première colonne et je veux que mon bloc de données regardez de la manière suivante
new_df:
EVNT_ID col1 col2 col3 col4 new_col 123454 1 Nan 4 5 1|4|5 628392 Nan 3 Nan 7 3|7 293899 2 Nan Nan 6 2|6 127820 9 11 12 19 9|11|12|19
J'utilise le code suivant
EVNT_ID col1 col2 col3 col4 123454 1 Nan 4 5 628392 Nan 3 Nan 7 293899 2 Nan Nan 6 127820 9 11 12 19
mais cela me donne l'erreur suivante
ufunc 'invert' non pris en charge pour les types d'entrée, et les entrées ne peuvent pas être forcées en toute sécurité à des types pris en charge selon la règle de conversion '' safe '' '
J'apprécierais vraiment que quelqu'un puisse me dire où je me trompe. J'apprécierais vraiment cela.
3 Réponses :
Vous pouvez le faire avec filter
et agg
:
df = pd.concat([df] * 1000, ignore_index=True) # In this post. %%timeit [ '|'.join([str(int(x)) for x in r if pd.notna(x)]) for r in df.iloc[:,1:].values.tolist() ] # RafaelC's answer. %%timeit [ '|'.join([k for k in a if k]) for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values.tolist()) ] 31.9 ms ± 800 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) 23.7 ms ± 409 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Ou,
joined = [ '|'.join([str(int(x)) for x in r if pd.notna(x)]) for r in df.iloc[:,1:].values.tolist() ] joined # ['1|4|5', '3|7', '2|6', '9|11|12|19'] df.assign(new_col=joined) EVNT_ID col1 col2 col3 col4 new_col 0 123454 1.0 NaN 4.0 5 1|4|5 1 628392 NaN 3.0 NaN 7 3|7 2 293899 2.0 NaN NaN 6 2|6 3 127820 9.0 11.0 12.0 19 9|11|12|19
Utilisation de la compréhension de liste et de zip
df = pd.concat([df]*1000) %timeit [['|'.join([k for k in a if k])] for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values)] 10.8 ms ± 568 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) %timeit df.filter(like='col').agg(lambda x: x.dropna().astype(int).astype(str).str.cat(sep='|'), axis=1) 1.68 s ± 91.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) %timeit df.iloc[:, 1:].apply(lambda x: '|'.join(str(el) for el in x if str(el) != 'nan'), axis=1) 87.8 ms ± 5.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit df.assign(new_col=['|'.join([str(int(x)) for x in r if ~np.isnan(x)]) for r in df.iloc[:,1:].values]) 45.1 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Le timing semble correct
>>> [['|'.join([k for k in a if k])] for a in zip(*df.fillna('').astype(str).iloc[:, 1:].values)]
Merci pour les horaires! Bien que ce ne soit pas une comparaison particulièrement juste à moins que la première composition de liste ne soit également attribuée, car cela entraîne une surcharge.
C'est vrai, mais n'ajoutera probablement pas beaucoup de frais généraux;)
Il suffit de faire la différence! J'ai également reflété vos horaires dans ma réponse.
Oui. vu ça. Merci pour les contributions! :}
Nos réponses ne sont pas non plus identiques. Votre code produit des flottants: ['1.0 | 2.0 | 9.0', '3.0 | 11.0', '4.0 | 12.0', '5 | 7 | 6 | 19']
@coldspeed Je vois, je dois str (int (float (k)))
ou quelque chose dans la boucle! Nous aurons le même temps, je crois:
Essayez le code suivant:
df['new_col'] = df.iloc[:, 1:].apply(lambda x: '|'.join(str(el) for el in x if str(el) != 'nan'), axis=1)
Au départ, j'ai pensé à x.dropna ()
au lieu de x if str (el)! = 'nan '
,
mais % timeit
a montré que dropna ()
fonctionne beaucoup plus lentement.