Je veux pouvoir concaténer une chaîne sur plusieurs lignes en une seule selon un identifiant. J'utilise la bibliothèque pandas (python 3).
val Cat Tiger Ball Bat bill dog
Cela fonctionne avec des boucles. j'ai besoin de ce résultat,
val id
Cat 1
Tiger 2
Ball 3
Bat 1
bill 2
dog 1
l = []
a = 0
while a < lendata:
if df["id"][a] == 1:
if a != 0:
df["val"][tmp] = ' '.join(l)
l = []
tmp = a
l.append(df["val"][a])
else:
l.append(df["val"][a])
a += 1
pas un groupe par
Question: Savez-vous comment le faire avec les fonctions pandas ? Merci.
3 Réponses :
np.split np.diff et trouvez où ces différences sont inférieures à zéro np.split la colonne val à ces positions [*map(' '.join, np.split(df.val, np.flatnonzero(df.id == 1)[1:]))]
pd.Series([*map(' '.join, np.split(df.val, np.flatnonzero(np.diff(df.id) < 0) + 1))])
0 Cat Tiger Ball
1 Bat
dtype: object
Utilisation de idée d'IanS de vérifier où id est égal à 1
[*map(' '.join, np.split(df.val, np.flatnonzero(np.diff(df.id) < 0) + 1))]
['Cat Tiger Ball', 'Bat']
Vous allez effrayer les nouveaux arrivants!
Devrions-nous ajouter "Ne pas apporter de réponses effrayantes" à la politique "Welcome Wagon"? @IanS
D'un autre côté, c'est toujours agréable de regarder du beau numpy-fu;)
@ jb255 Ne vous sentez pas obligé d'accepter ma réponse parce que j'étais le premier. Si la réponse d'IanS vous convient mieux, veuillez accepter la sienne. Si vous aimez ma réponse mieux que par tous les moyens, faites ce que vous aimez (-:
Rester dans les pandas:
id val 0 1 Cat Tiger Ball 1 2 Bat bill 2 3 dog
df['group'] = (df['id'] == 1).cumsum()
df.groupby('group')['val'].apply(' '.join).reset_index()
La première ligne définit les groupes selon votre définition. La deuxième ligne est une opération groupby standard.
Cela vous dérange si j'ajoute un dataframe à votre réponse? Je reproduisais la même réponse pourrais aussi bien l'ajouter à la vôtre
Ou df.groupby ((df ['id'] == 1) .cumsum ()) ['val']. Apply ('' .join) .reset_index ()
En fait, j'avais exactement cette réponse, mais c'était trop proche de sa réponse d'IanS pour la publier comme nouvelle réponse @jezrael
Vous pouvez également créer un tableau comme ceci:
In [1] : df.groupby(['regroup'])['val'].apply(' '.join)
Out[1] : regroup
-2 Bat
1 Cat Tiger Ball
Ensuite, vous créez une troisième colonne qui équivaut à votre id moins le tableau précédent. Cette troisième colonne vous montrera quels val sont ensemble.
id val regroup 0 1 Cat 1 1 2 Tiger 1 2 3 Ball 1 3 1 Bat -2
Out:
df['regroup'] = df['id'].subtract(a)
Vous pouvez maintenant utiliser un groupe par pour avoir le résultat souhaité:
a = np.array(range(len(df)))
Solution intéressante, assez créative!
Assez élégant! Vous pouvez également le faire en une seule ligne: df ['id']. Subtract (np.arange (len (df))) ...
IIUC
df.groupby ('id'). Val.apply ('' .join) .reset_index ()Btw, je comprends que vous venez probablement de vous lancer dans
pandas, mais l'utilisation des bouclesfor / ifimbriquées est lente par rapport à la fonction pandas disponible. Investissez du temps pour apprendre les pandas et pour 90% de vos problèmes, pandas leur apporte une solution en termes de fonctions / méthodes.@piRSquared nous avons mal compris, vérifiez sa sortie attendue
@ jb255 Vous devriez probablement expliquer pourquoi les lignes particulières de
iddéfinissent un groupe. Je suppose que la nature consécutive est ce que cela fait.Bienvenue dans StackOverflow! Je pense que vous pouvez maintenant comprendre pourquoi il est essentiel de montrer le résultat attendu et de fournir un véritable exemple reproductible minimal qui d'autres peuvent simplement copier et coller :-)