Flatten a JSON file in Pandas
I am trying to change a JSON file to a pandas DataFrame. I have tried a number of solution such as pd.jason_normalize(data.json) but it doesn't work.
The file appears to be more complex and has nested JSON data. How do I flatten this file so I can read the contents as a DataFrame?
Images are to give context on he structure
[![enter image description here][1]][1]
data = pd.read_json("papers.json")
>>>(Output)
data.head(5)
paper
0 {'id': 1, 'preliminary_decision': 'accept', 'r...
1 {'id': 2, 'preliminary_decision': 'accept', 'r...
2 {'id': 3, 'preliminary_decision': 'accept', 'r...
3 {'id': 4, 'preliminary_decision': 'accept', 'r...
4 {'id': 5, 'preliminary_decision': 'accept', 'r...
>>>(Output)
paper[0]
{'id': 1, 'preliminary_decision': 'accept', 'review': > [{'confidence': '4', 'evaluation': '1', 'id': 1, 'lan': 'es', > 'orientation': '0', 'remarks: '', 'text': '- El artículo aborda > un problema contingente y muy relevante, e incluye tanto un > diagnóstico nacional de uso de buenas prácticas como una solución > (buenas prácticas concretas). - El lenguaje es adecuado. - El > artículo se siente como la concatenación de tres artículos diferentes: > (1) resultados de una encuesta, (2) buenas prácticas de seguridad, (3) > incorporación de buenas prácticas. - El orden de las secciones sería > mejor si refleja este orden (la versión revisada es #2, #1, #3). - El > artículo no tiene validación de ningún tipo, ni siquiera por > evaluación de expertos.', 'timespan': '2010-07-05'},
> {'confidence': '4', 'evaluation': '1', 'id': 2, 'lan': 'es', > 'orientation': '1', 'remarks': '', 'text': 'El artículo presenta > recomendaciones prácticas para el desarrollo de software seguro. Se > describen las mejores prácticas recomendadas para desarrollar software > que sea proactivo ante los ataques, y se realiza un análisis de costos > de estas prácticas en desarrollo de software. Todo basado en una > revisión de prácticas propuestas en la bibliografía y su contraste con > datos obtenidos de una encuesta en empresas. Finalmente se recomienda > una guía. Sería ideal aplicar la guía propuesta a empresas no > involucradas en la encuesta que sirvió para originarla de modo de > poder evaluar su efectividad en forma independiente.', 'timespan': > '2010-07-05'}, {'confidence': '5', 'evaluation': '1', 'id': 3, > 'lan': 'es', 'orientation': '1', 'remarks': '', 'text': '- El > tema es muy interesante y puede ser de mucha ayuda una guía para > incorporar prácticas de seguridad. - La presentación (descripción, > etapa y uso) de las 9 prácticas para el desarrollo de software seguro. > - El “estado real del desarrollo de software en Chile” (como lo indica en su paper) no se puede lograr con solamente 22 encuestas de un total > de 50. - Presenta nueve tablas que corresponden a las prácticas para > el desarrollo de software seguro, pero la guía presenta 10 prácticas. > ¿explica por qué? - Sugiero mejorar la guía, el mayor aporte está en > la secuencia de incorporación que propone. Además, no debería > explicar la práctica en Observaciones ni diferenciarla con otras > prácticas en esa columna, sino que debería dar sugerencias de cómo > aplicarla. - En el texto indica “Más adelante, se presentan además > tres prácticas extras…” ¿cuáles son o no leí correctamente? - De > acuerdo a formato, poner como mínimo 5 palabras clave. - Sugiero > mencionar las prácticas antes de mostrar cada tabla. - Algunas > referencias están incompletas, por ejemplo, falta año en referencia > 17, falta año y tipo de evento en referencia 11, falta editorial en > referencia 19 (¿es un libro?) - Algunos títulos llevan una coma dentro > de las comillas, ejemplo, referencia 1', 'timespan': > '2010-07-05'}]}
( Expected Output)
[ id, preliminary_decision, review, confidence, evaluation, id, lan, orientation, remarks, text, timespan']
Solution 1:
You can use some parameters to json_normalize
to achieve what you like to get.
Assuming data
is a dataframe and you have JSON object in paper column.
pd.json_normalize(data.paper, record_path=['review'], meta=['id', 'preliminary_decision'], meta_prefix='paper.')
You need to use either record_prefix
or meta_prefix
to avoid conflicts of columns, since you have id
in root and within review
array.
Solution 2:
Similar question here
But in your case you only want the last key to be considered
def flatten_data(data):
out = {}
def flatten(x, name=''):
if type(x) is dict:
for a in x:
flatten(x[a], a)
elif type(x) is list:
i = 0
for i,a in enumerate(x):
flatten(a, i)
else:
out[name] = x
flatten(data);
return out
df = pd.DataFrame([flatten(y) for y in data]);