преобразование JSON с другим форматом в CSV - PullRequest
2 голосов
/ 07 октября 2019

Я знаю, что об этом спрашивали много раз, но у меня все еще нет решения моей проблемы, и я не настолько хорош в программировании, поэтому в основном у меня так много файлов json, но формат json сильно отличается, поэтому я могуне получается вывод, который я хочу с библиотекой панд, вот пример файла 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"
        ]
    }
]

, когда я преобразовал это с пандами, используя этот простой код:

import json
import pandas as pd

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

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

проблема в том, что выходной файл csv дает мне все 3 имени в одной ячейке, как это ['Джеймс', 'Боб', 'Дэвид'], ['2000 $', '5000 $', '6000 $'] ... но я хочу, чтобы в ячейке было только одно имя, а не все 3 из них. Я очень новичок в этом, я буду признателен за любую помощь

Ответы [ 5 ]

1 голос
/ 07 октября 2019

Да, вы получаете этот ответ, потому что каждое значение для данного ключа в словаре содержит список, а не один элемент. Поэтому существует два уровня, на которые следует обратить внимание при работе с таким форматом json.

data - список, содержащий два словаря с одинаковыми ключами каждый. Любой словарь содержит ключи, которые содержат список. Поэтому нам нужно выполнить итерацию по первому списку (для адресации каждого словаря), а затем по второму, чтобы адресовать каждое значение для любого указанного ключа. Результатом будет таблица по вашему желанию. Следует отметить, что этот код будет работать, так как длина значений списка "Names" равна "Salary" и "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)

Вывод:

     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
0 голосов
/ 07 октября 2019

Я думаю, вы хотите, чтобы в каждой строке были идентификатор, имя и зарплата. Вы можете добиться этого следующим образом:

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")

результат в 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$

В основном исходный фрейм данных df содержит в списках идентификатор, имена и данные о зарплате, так чтовам нужно создать новый фрейм данных new_df, затем выполнить цикл по фрейму данных df и добавить к new_df фрейм данных (с такой же структурой, что и df_new), который имеет значения строк в каждом столбце.

Это будет работать независимо от длины списков в строках, если они одинаковы для идентификатора, имен и зарплаты ...

0 голосов
/ 07 октября 2019

Ваш ввод данных не структурирован должным образом для того, что вы хотели, вам нужно сначала исправить это:

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'])

Результат:

  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 голосов
/ 07 октября 2019

Проблема не в функции, а в способе определения json. Поэтому вывод pandas точно такой, каким он должен быть.

Вместо того, чтобы читать его по-другому, вы можете просто отформатировать свой фрейм данных дальше, чтобы показать желаемый результат. На данный момент каждая строка для каждого столбца является списком, поэтому вам необходимо удалить:

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'])

Самостоятельная функция отмены сообщений доступна благодаря WeNYoBen

0 голосов
/ 07 октября 2019
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"
        ]
    }
]

Я думаю, что это может решить вашу проблему:

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

Вывод: '

  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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...