Tout d’abord, je suis très novice chez Pandas et j’essaie de me pencher afin que des réponses approfondies soient appréciées.
Je veux générer un DataFrame de pandas représentant une carte witter tag subtoken -> poster
où tag subtoken signifie n'importe quoi dans le set {hashtagA} U {i | i in split("_", hashtagA)}
à partir d'une table correspondant poster -> tweet
Par exemple:
In [1]: df = pd.DataFrame([["jim", "i was like #yolo_omg to her"], ["jack", "You are so #yes_omg #best_place_ever"], ["neil", "Yo #rofl_so_funny"]])
In [2]: df
Out[2]:
0 1
0 jim i was like #yolo_omg to her
1 jack You are so #yes_omg #best_place_ever
2 neil Yo #rofl_so_funny
Et à partir de cela, je veux obtenir quelque chose comme
0 1
0 jim yolo_omg
1 jim yolo
2 jim omg
3 jack yes_omg
4 jack yes
5 jack omg
6 jack best_place_ever
7 jack best
8 jack place
9 jack ever
10 neil rofl_so_funny
11 neil rofl
12 neil so
13 neil funny
J'ai réussi à construire cette mostrosité qui fait le travail:
In [143]: df[1].str.findall("#([^s]+)")
.apply(pd.Series).stack()
.apply(lambda s: [s] + s.split("_") if "_" in s else [s])
.apply(pd.Series).stack().to_frame().reset_index(level=0)
.join(df, on="level_0", how="right", lsuffix="_l")[["0","0_l"]]
Out[143]:
0 0_l
0 0 jim yolo_omg
1 jim yolo
2 jim omg
0 jack yes_omg
1 jack yes
2 jack omg
1 0 jack best_place_ever
1 jack best
2 jack place
3 jack ever
0 0 neil rofl_so_funny
1 neil rofl
2 neil so
3 neil funny
Mais j’ai le sentiment très fort qu’il existe de bien meilleures façons de le faire, d’autant plus que le véritable ensemble de données est énorme.
Réponses:
1 pour la réponse № 1les pandas ont en effet une fonction pour le faire nativement. Series.str.findall () Cela applique essentiellement une expression rationnelle et capture le (s) groupe (s) que vous spécifiez dans celle-ci.
Donc, si j'avais votre dataframe:
df = pd.DataFrame([["jim", "i was like #yolo_omg to her"], ["jack", "You are so #yes_omg #best_place_ever"], ["neil", "Yo #rofl_so_funny"]])
Ce que je voudrais faire est d’abord de définir les noms de vos colonnes, comme ceci:
df.columns = ["user", "tweet"]
Ou faites-le à la création du cadre de données:
df = pd.DataFrame([["jim", "i was like #yolo_omg to her"], ["jack", "You are so #yes_omg #best_place_ever"], ["neil", "Yo #rofl_so_funny"]], columns=["user", "tweet"])
Ensuite, je voudrais simplement appliquer la fonction d'extraction avec une expression régulière:
df["tag"] = df["tweet"].str.findall("(#[^ ]*)")
Et j'utiliserais le groupe de caractères négatifs au lieu d'un groupe positif, il est plus susceptible de survivre à des cas particuliers.
0 pour la réponse № 2
Que diriez-vous d'utiliser des listes de compréhension en python puis de revenir aux pandas? Nécessite quelques lignes de code mais est peut-être plus lisible.
import re
récupère les balises de hachage
tags = [re.findall("#([^s]+)", t) for t in df[1]]
faire des listes de tags avec des sous-mots pour chaque utilisateur
st = [[t] + [s.split("_") for s in t] for t in tags]
subtokens = [[i for s in poster for i in s] for poster in st]
remettre dans DataFrame avec les noms des affiches
df2 = pd.DataFrame(subtokens, index=df[0]).stack()
In [250]: df2
Out[250]:
jim 0 yolo_omg
1 yolo
2 omg
jack 0 yes_omg
1 best_place_ever
2 yes
3 omg
4 best
5 place
6 ever
neil 0 rofl_so_funny
1 rofl
2 so
3 funny
dtype: object