简体   繁体   中英

how to split dictionary to separate rows in pandas

I have a dataframe like this:

  | col1 | d
-------------------------------------------
0 | A    | {'student99': [[0.83, "nice"]]}
1 | B    | {'student99': [[0.84, "great"], [0.89, "cool"]]}
2 | C    | {'student98': [[0.85, "amazing"]], 'student97': [[0.9, "crazy"]]}

And I'm trying to convert to a dataframe like:

  | col1 | student  | grade | comment
---------------------------------------------
0 | A    | student99| 0.83  | nice
1 | B    | student99| 0.84  | great
2 | B    | student99| 0.89  | cool 
3 | C    | student98| 0.85  | amazing 
4 | C    | student97| 0.9   | crazy

Like you can see, I need to split d column to student , grade and comment columns and I need to split the row to some rows by the number of keys in d column (like row C above) and by the number of lists per key (like row B above).

How can I do that?

Following the comment, I note that the data arrived as JSON in the next format (I convert it to dataframe):

{"A": {"d" : {'student99': [[0.83, "nice"]]}}, 
 "B": {"d" : {'student99': [[0.84, "great"], [0.89, "cool"]]},
 "C": {"d" : {'student98': [[0.85, "amazing"]], 'student97': [[0.9, "crazy"]]}
}

We can do explode with pd.Series then recreate the dataframe join it back

s=df.pop('d').apply(pd.Series).stack().explode()
df_add=pd.DataFrame({'student':s.index.get_level_values(1),
                      'grade':s.str[0].values,
                      'comment':s.str[1].values},
                     index=s.index.get_level_values(0))
df=df.join(df_add,how='right')
df
Out[169]: 
    col1    student  grade  comment
0  A      student99   0.83     nice
1  B      student99   0.84    great
1  B      student99   0.89     cool
2  C      student98   0.85  amazing
2  C      student97   0.90    crazy

@YOBEN_S' solution is great; this is an attempt at a faster solution:

from itertools import product, chain

#chain.... is long... flatten is shorter
#and still gets the point accross
flatten = chain.from_iterable

#flatten the product of each key,value pair 
#in the dictionary
m = [(first, flatten(product([key], value) for key, value in last.items()))
     for first, last in emp]

#flatten again
phase2 = flatten(product(first, last) for first, last in m)

#at this point we have 
#the column entry("A","B",...)
#and the flattened entries in the dict
#so, unpacking solves this
phase3 = [(first,second, *last) for first, (second,last) in phase2]

result = pd.DataFrame(phase3, columns = ["col1","student","grade","comment"])

result


    col1    student grade   comment
0   A   student99   0.83    nice
1   B   student99   0.84    great
2   B   student99   0.89    cool
3   C   student98   0.85    amazing
4   C   student97   0.90    crazy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM