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.