【问题标题】:Convert JSON file to Pandas dataframe将 JSON 文件转换为 Pandas 数据框
【发布时间】:2020-02-29 19:24:37
【问题描述】:

我想将 JSON 转换为 Pandas 数据框。

我的 JSON 看起来像: 喜欢:

{ 
   "country1":{ 
      "AdUnit1":{ 
         "floor_price1":{ 
            "feature1":1111,
            "feature2":1112
         },
         "floor_price2":{ 
            "feature1":1121
         }
      },
      "AdUnit2":{ 
         "floor_price1":{ 
            "feature1":1211
         },
         "floor_price2":{ 
            "feature1":1221
         }
      }
   },
   "country2":{ 
      "AdUnit1":{ 
         "floor_price1":{ 
            "feature1":2111,
            "feature2":2112
         }
      }
   }
}

我使用以下代码从 GCP 读取文件:

project = Context.default().project_id
sample_bucket_name = 'my_bucket'
sample_bucket_path = 'gs://' + sample_bucket_name
print('Object: ' + sample_bucket_path + '/json_output.json')

sample_bucket = storage.Bucket(sample_bucket_name)
sample_bucket.create()
sample_bucket.exists()

sample_object = sample_bucket.object('json_output.json')
list(sample_bucket.objects())
json = sample_object.read_stream()

我的目标是获得如下所示的 Pandas 数据框:

我尝试使用json_normalize,但没有成功。

【问题讨论】:

  • pd.read_json 怎么样?
  • 我试过了,结果不好:c2n.me/44pYvfb
  • 看看this的回答,因为我认为你需要先将json“展平”才能使用pd.read_json(json.dumps(json_dictionary))

标签: python json pandas dataframe


【解决方案1】:

你可以试试这个方法:

 from google.cloud import storage
 import pandas as pd

 storage_client = storage.Client()
 bucket = storage_client.get_bucket('test-mvladoi')
 blob = bucket.blob('file')
 read_output = blob.download_as_string()
 data = json.loads(read_output)

 data_norm = json_normalize(data, max_level=5)
 df = pd.DataFrame(columns=['col1', 'col2', 'col3', 'col4', 'col5'])
 i = 0

 for col in b.columns:
     a,c,d,e = col.split('.')
     df.loc[i]  = [a,c,d,e,b[col][0]]
     i = i + 1

 print(df)

【讨论】:

  • 我在 Google 数据实验室工作,from google.cloud import storage 存在一些问题
  • 试过了。 AttributeError: module 'google.datalab.storage' has no attribute 'Client'
  • 他们处理存储的方式不同:mybucket = storage.Bucket('BUCKET_NAME'), blob = mybucket.object('file') 在网上看
【解决方案2】:

不是最好的方法,但它的工作。此外,您还应该修改仅从此 awnser 中挑选的 flatten 函数

test = { 
   "country1":{ 
      "AdUnit1":{ 
         "floor_price1":{ 
            "feature1":1111,
            "feature2":1112
         },
         "floor_price2":{ 
            "feature1":1121
         }
      },
      "AdUnit2":{ 
         "floor_price1":{ 
            "feature1":1211
         },
         "floor_price2":{ 
            "feature1":1221
         }
      }
   },
   "country2":{ 
      "AdUnit1":{ 
         "floor_price1":{ 
            "feature1":2111,
            "feature2":2112
         }
      }
   }
}

from collections import defaultdict
import pandas as pd
import collections

def flatten(d, parent_key='', sep='_'):
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, collections.MutableMapping):
            items.extend(flatten(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)

results = defaultdict(list)   
colnames = ["col1", "col2", "col3", "col4", "col5", "col6"]
for key, value in flatten(test).items():
    elements = key.split("_")
    elements.append(value)
    for colname, element in zip(colnames, elements):
        results[colname].append(element)

df = pd.DataFrame(results)
print(df)

【讨论】:

    【解决方案3】:

    你可以用这个:

    def flatten_dict(d):
        """ Returns list of lists from given dictionary """
        l = []
        for k, v in sorted(d.items()):
            if isinstance(v, dict):
                flatten_v = flatten_dict(v)
                for my_l in reversed(flatten_v):
                    my_l.insert(0, k)
    
                l.extend(flatten_v)
    
            elif isinstance(v, list):
                for l_val in v:
                    l.append([k, l_val])
    
            else:
                l.append([k, v])
    
        return l
    

    这个函数接收一个字典(包括值也可以是列表的嵌套)并将其展平为列表列表。

    那么,你可以简单地:

    df = pd.DataFrame(flatten_dict(my_dict))
    

    my_dict 是您的 JSON 对象。 以您为例,运行print(df) 时得到的是:

              0        1             2         3     4
    0  country1  AdUnit1  floor_price1  feature1  1111
    1  country1  AdUnit1  floor_price1  feature2  1112
    2  country1  AdUnit1  floor_price2  feature1  1121
    3  country1  AdUnit2  floor_price1  feature1  1211
    4  country1  AdUnit2  floor_price2  feature1  1221
    5  country2  AdUnit1  floor_price1  feature1  2111
    6  country2  AdUnit1  floor_price1  feature2  2112
    

    当你创建数据框时,你可以命名你的列和索引

    【讨论】:

      【解决方案4】:

      嵌套的 JSON 总是很难正确处理。

      几个月前,我想出了一种方法来提供一个“通用答案”,使用来自here 的编写精美的flatten_json_iterative_solution:它迭代地解包每个级别给定的 json。

      然后可以简单地将其转换为 Pandas.Series 然后 Pandas.DataFrame 像这样:

      df = pd.Series(flatten_json_iterative_solution(dict(json_))).to_frame().reset_index()
      

      Intermediate Dataframe result

      可以很容易地执行一些数据转换来拆分您要求的列名中的索引:

      df[["index", "col1", "col2", "col3", "col4"]] = df['index'].apply(lambda x: pd.Series(x.split('_')))
      

      Final result

      【讨论】:

        猜你喜欢
        • 2019-05-14
        • 2019-07-01
        • 2021-12-13
        • 1970-01-01
        • 1970-01-01
        • 2020-10-31
        • 1970-01-01
        • 2019-09-25
        • 2022-01-10
        相关资源
        最近更新 更多