Reconstruire les pandas Dataframe

Nov 05 2020

Im assez nouveau sur Python. J'ai du mal à reconstruire un mauvais Dataframe. Mon Dataframe ressemble à ceci:

df = pd.DataFrame({'col1': ['id 1', 'id 2', 'test 3', 'test 4'],
               'col2': ['test 1', 'test 2',
                        'Number 6135', 'id 4'],
               'col3': ['Number 12344', 'Number 21612','id 3','Number 1131']})

Comme vous pouvez le voir, j'ai les "id´s" dans le premier, deuxième et troisième col. Idem pour les autres Valeurs.

Mon objectif est d'avoir un Dataframe dans lequel chaque Col n'a que les Valeurs commençant par la même sous-chaîne comme cet exemple:

J'ai déjà essayé d'utiliser des boucles for et if Statments pour vérifier si une certaine sous-chaîne est dans ma chaîne. si c'est vrai, je crée une nouvelle colonne et j'écris ma valeur à l'intérieur

for x in df['col1']:
if 'id' in x:
    df['newCol']=x

Je sais que ce code ne résoudra jamais mon problème, peut-être qu'il existe une fonction pandas qui peut m'aider à résoudre ce problème

Si quelque chose n'est pas clair, demandez-moi simplement que je ferai de mon mieux pour expliquer mon problème. Merci d'avance pour votre aide et allez-y doucement :)

Réponses

3 AndrejKesely Nov 05 2020 at 17:34

Vous pouvez utiliser sorted()avec la fonction de touche personnalisée:

def key_fn(x):
    if 'id' in x:
        return 0
    if 'test' in x:
        return 1
    if 'Number' in x:
        return 2
    return 3 

df = df.apply(lambda x: pd.Series(sorted(x, key=key_fn)), axis=1)
df = df.rename(columns=lambda x: 'col{}'.format(x+1))
print(df)

Impressions:

   col1    col2          col3
0  id 1  test 1  Number 12344
1  id 2  test 2  Number 21612
2  id 3  test 3   Number 6135
3  id 4  test 4   Number 1131

Une autre version, d'après les commentaires:

df = pd.DataFrame([sorted(l, key=key_fn) for l in df.values], columns=df.columns)
print(df)
3 jezrael Nov 05 2020 at 17:34

Si possible, simplifiez la solution en fractionnant les valeurs par le premier vide:

df = (df.reset_index()
        .melt('index')
        .assign(new = lambda x: x['value'].str.split().str[0])
        .pivot('index','new','value'))
print (df)
new          Number    id    test
index                            
0      Number 12344  id 1  test 1
1      Number 21612  id 2  test 2
2       Number 6135  id 3  test 3
3       Number 1131  id 4  test 4

Sinon, vous pouvez utiliser Series.str.extract:

L = ['id','test','Number']

df = (df.reset_index()
        .melt('index')
        .assign(new = lambda x: x['value'].str.extract(f'({"|".join(L)})', expand=False))
        .pivot('index','new','value'))
print (df)
new          Number    id    test
index                            
0      Number 12344  id 1  test 1
1      Number 21612  id 2  test 2
2       Number 6135  id 3  test 3
3       Number 1131  id 4  test 4
AndyL. Nov 05 2020 at 17:38

Essaye ça:

s = df.melt()['value']
df_final = pd.DataFrame({x: s[s.str.startswith(x)].values 
                                        for x in s.str.split().str[0].unique()})

Out[27]:
     id    test        Number
0  id 1  test 3   Number 6135
1  id 2  test 4  Number 12344
2  id 4  test 1  Number 21612
3  id 3  test 2   Number 1131
sammywemmy Nov 05 2020 at 17:48

Vous pouvez d'abord fondre le dataframe, puis utiliser numpy select pour réorganiser les noms, et enfin pivoter :

(df.melt(ignore_index=False)
   .assign(variable=lambda x: np.select([x.value.str.startswith("id"),
                                          x.value.str.startswith("test"),
                                          x.value.str.startswith("Number")],
                                          ["col1", "col2", "col3"]))
    .reset_index()
    .pivot("index", "variable", "value")
    .rename_axis(columns=None, index=None))


    col1    col2    col3
0   id 1    test 1  Number 12344
1   id 2    test 2  Number 21612
2   id 3    test 3  Number 6135
3   id 4    test 4  Number 1131