Sé que esto se ha preguntado muchas veces, pero todavía no tengo solución para mi problema y no soy tan bueno en la programación, así que básicamente tengo tantos archivos json, pero el formato de json es muy diferente, así que no puedo obtener el resultado que quiero con la biblioteca de pandas, aquí hay un ejemplo del archivo json.

[
    {
        "Names": [
            "James",
            "Bob",
            "David"
        ],
        "Salary": [
            "2000$",
            "5000$",
            "6000$"
        ],
        "Id": [
            "1",
            "2",
            "3"
        ]
    },
    {
        "Names": [
            "John",
            "Charles",
            "Harry"
        ],
        "Salary": [
            "1000$",
            "2000$",
            "3000$"
        ],
        "Id": [
            "4",
            "5",
            "6"
        ]
    }
]

Cuando convertí esto con pandas usando este código simple:

import json
import pandas as pd

df=pd.read_json("test.json")
df.to_csv("results.csv")

https://i.imgur.com/0RMLb89.png

El problema es que la salida del archivo csv me da los 3 nombres en una sola celda como esa ['James', 'Bob', 'David'], ['2000 $', '5000 $', '6000 $' ] ... pero solo quiero un nombre en la celda, no los tres. Soy muy nuevo en estas cosas, agradeceré cualquier ayuda

2
Rei M 7 oct. 2019 a las 15:40

5 respuestas

La mejor respuesta

Creo que desea que cada fila tenga la identificación, el nombre y el salario. Puede lograr esto de la siguiente manera:

import pandas as pd

df=pd.read_json("test.json")

new_df = pd.DataFrame(columns=['id', 'name', 'salary'])
for _, row in df.iterrows():
    new_df = new_df.append(pd.DataFrame(
        {'id': row.Id, 'name': row.Names, 'salary': row.Salary}))

new_df.to_csv("results.csv")

Resultar en results.csv

,id,name,salary
0,1,James,2000$
1,2,Bob,5000$
2,3,David,6000$
0,4,John,1000$
1,5,Charles,2000$
2,6,Harry,3000$

Básicamente, el marco de datos inicial df tiene la identificación, los nombres y los datos salariales en las listas, por lo que lo que debe hacer es crear un nuevo marco de datos new_df, luego recorrer el marco de datos df y agregar a {{ X3}} el marco de datos (con la misma estructura que df_new) que tiene los valores de las filas correctamente debajo de cada columna.

Esto funcionará sin importar cuánto tiempo sean las listas en filas, siempre que sean las mismas para Id, Nombres y Salario ...

0
Bruno Vermeulen 7 oct. 2019 a las 14:09
a = [
    {
        "Names": [
            "James",
            "Bob",
            "David"
        ],
        "Salary": [
            "2000$",
            "5000$",
            "6000$"
        ],
        "Id": [
            "1",
            "2",
            "3"
        ]
    },
    {
        "Names": [
            "John",
            "Charles",
            "Harry"
        ],
        "Salary": [
            "1000$",
            "2000$",
            "3000$"
        ],
        "Id": [
            "4",
            "5",
            "6"
        ]
    }
]

Creo que esto podría resolver tu problema:

col_names = [k for k,v in a[0].items()]
frames = [pd.io.json.json_normalize(a, str(col)) for col in col_names]
final_df = pd.concat(frames, axis = 1)
final_df.columns = col_names

Salida: '

  Id Salary    Names
0  1  2000$    James
1  2  5000$      Bob
2  3  6000$    David
3  4  1000$     John
4  5  2000$  Charles
5  6  3000$    Harry
0
naive 7 oct. 2019 a las 13:06

El problema no está en la función sino en la forma en que se define el json. La salida de pandas es, por tanto, exactamente como debería ser.

En lugar de leerlo de manera diferente, simplemente puede formatear su marco de datos para mostrar el resultado que desea. Por el momento, cada fila de cada columna es una lista, por lo que debe anular:

import json
import pandas as pd
import numpy as np

df=pd.read_json('data.json')

def unnesting(df, explode):
    idx = df.index.repeat(df[explode[0]].str.len())
    df1 = pd.concat([
        pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
    df1.index = idx

    return df1.join(df.drop(explode, 1), how='left')

unnesting(df,['Names','Salary','Id'])

La función de descompresión hecha a sí misma viene gracias a WeNYoBen

0
Fnguyen 7 oct. 2019 a las 12:59

Su entrada de datos no está estructurada correctamente para la salida que deseaba, primero deberá arreglar eso:

import json

with open('test.json', 'r') as file:
    data = json.load(file.read())

# flatten the data to {'Name': [...], 'Salary': [...], ...}
d = {}
for elem in data:
    for k, v in elem.items():
        d.setdefault(k, []).extend(v)

df = pd.DataFrame(d).reindex(columns=['Id', 'Names', 'Salary'])

Resultado:

  Id    Names Salary
0  1    James  2000$
1  2      Bob  5000$
2  3    David  6000$
3  4     John  1000$
4  5  Charles  2000$
5  6    Harry  3000$
0
r.ook 7 oct. 2019 a las 13:07

Sí, está obteniendo esa respuesta porque cada valor para la clave dada en el diccionario contiene una lista y no un solo elemento. Por lo tanto, hay dos niveles que debe abordar cuando trabaje con ese tipo de formato json.

data es una lista que contiene dos diccionarios con las mismas claves cada uno. Cualquiera de los diccionarios contiene claves que contienen una lista. Por lo tanto, necesitamos iterar sobre la primera lista (para abordar cada diccionario) y luego sobre la segunda para abordar cada valor para cualquier clave especificada. El resultado será la tabla que desee. Cabe señalar que este código funcionará ya que la longitud de los valores de la lista de "Names" es la misma que "Salary" y "Id".

import pandas as pd 
import numpy as np
data = [
    {
        "Names": ["James","Bob","David"],
        "Salary": ["2000$","5000$","6000$"],
        "Id": ["1","2","3"]},
    {
        "Names": ["John","Charles","Harry"],
        "Salary": ["1000$","2000$","3000$"],
        "Id": ["4","5","6"]}
]
to_df = {'Names':[],'Salary':[],'Id':[]}
for i in range(len(data)):
    for j in range(len(data[i]['Id'])):
        to_df['Names'].append(data[i]['Names'][j])
        to_df['Salary'].append(data[i]['Salary'][j])
        to_df['Id'].append(data[i]['Id'][j])
df = pd.DataFrame(to_df)
print(df)

Salida:

     Names Salary Id
0    James  2000$  1
1      Bob  5000$  2
2    David  6000$  3
3     John  1000$  4
4  Charles  2000$  5
5    Harry  3000$  6
1
Celius Stingher 7 oct. 2019 a las 14:05
58269752