J'ai un dictionnaire où les clés sont les identifiants des patients et les valeurs sont les mêmes pour toutes les clés: [1, 2, 3], indiquant que chaque patient se rendra à la clinique 3 fois. Comment puis-je le convertir en une trame de données où les clés et les valeurs sont des lignes?

Dictionnaire:

patients = ['Patient01', 'patient02', 'patient03']
visits = [1,2,3]
dictionary = {k:visits for k in patients}

Production:

{'Patient01': [1, 2, 3],
 'patient02': [1, 2, 3],
 'patient03': [1, 2, 3]}

J'ai essayé

pd.DataFrame.from_dict(dictionary, orient = 'index')

Mais la sortie est

            0   1   2
patient02   1   2   3
patient03   1   2   3
patient01   1   2   3

Et ce que je veux c'est comme ça:

          visit_num
patient01  1
patient01  2
patient01  3
patient02  1
patient02  2
patient02  3
patient03  1
patient03  2
patient03  3
3
Karen Liu 11 avril 2018 à 18:52

6 réponses

Meilleure réponse
data = [[patient, visit_num]
        for patient, visits in dictionary.items()
        for visit_num in visits]
df = pd.DataFrame(data, columns=['patient', 'visit_num']).set_index('patient')
2
Alex Hall 11 avril 2018 à 16:01

Utilisez melt :

df = pd.DataFrame.from_dict(dictionary, orient = 'index')
df.reset_index()\
  .melt('index',value_name='visit_num')\
  .drop('variable', axis=1)\
  .sort_values('index') #if you wish to get your order

Production:

       index  visit_num
1  Patient01          1
4  Patient01          2
7  Patient01          3
2  patient02          1
5  patient02          2
8  patient02          3
0  patient03          1
3  patient03          2
6  patient03          3
4
Scott Boston 11 avril 2018 à 15:56

Directement d'une compréhension

pd.Series(
    *zip(*((v, k) for k, c in dictionary.items() for v in c))
).to_frame('visit_num')

           visit_num
Patient01          1
Patient01          2
Patient01          3
patient02          1
patient02          2
patient02          3
patient03          1
patient03          2
patient03          3
4
piRSquared 11 avril 2018 à 16:01

Utilisez pd.stack() sur le trame de données que vous avez créée:

df = pd.DataFrame.from_dict(dictionary, orient = 'index')

new_df = df.stack().reset_index(level=1, drop=True).to_frame(name='visit_num')

>>> new_df
           visit num
Patient01          1
Patient01          2
Patient01          3
patient02          1
patient02          2
patient02          3
patient03          1
patient03          2
patient03          3

Note d'explication :

df.stack fait la majeure partie du travail ici, en prenant votre original df

           0  1  2
Patient01  1  2  3
patient02  1  2  3
patient03  1  2  3

Et le transforme en pandas.Series multi-indexé suivant:

Patient01  0    1
           1    2
           2    3
patient02  0    1
           1    2
           2    3
patient03  0    1
           1    2
           2    3

Le reste de la ligne (.reset_index() et .to_frame()) est simplement là pour le mettre dans un joli format de trame de données.

6
sacuL 11 avril 2018 à 16:08

Vous pouvez utiliser itertools.product pour simplement résoudre votre problème, suivi de pd.DataFrame.set_index.

import pandas as pd
from itertools import product

patients = ['Patient01', 'patient02', 'patient03']
visits = [1, 2, 3]

df = pd.DataFrame(list(product(patients, visits)), columns=['patients', 'visit_num'])\
       .set_index('patients')
2
jpp 11 avril 2018 à 15:56

Vous pouvez peut-être essayer avec numpy

pd.DataFrame({'visit_num':np.hstack(list(dictionary.values()))},index=np.repeat(list(dictionary.keys()),len(dictionary)))
Out[76]: 
           visit_num
Patient01          1
Patient01          2
Patient01          3
patient02          1
patient02          2
patient02          3
patient03          1
patient03          2
patient03          3
2
YOBEN_S 11 avril 2018 à 16:11