[英]Pyspark - get attribute names from json file
我是 pyspark 的新手。 我的要求是從嵌套的 json 文件中獲取/提取屬性名稱。 我嘗試使用從 Pandas 包導入的 json_normalize。 它適用於直接屬性,但從不獲取 json 數組屬性中的屬性。 我的 json 沒有靜態結構。 它因我們收到的每份文件而異。 有人可以幫我解釋下面提供的小例子嗎,
{
"id":"1",
"name":"a",
"salaries":[
{
"salary":"1000"
},
{
"salary":"5000"
}
],
"states":{
"state":"Karnataka",
"cities":[
{
"city":"Bangalore"
},
{
"city":"Mysore"
}
],
"state":"Tamil Nadu",
"cities":[
{
"city":"Chennai"
},
{
"city":"Coimbatore"
}
]
}
}
特別是對於json數組元素..
預期輸出:id 名稱salary.salary states.state states.cities.city``
這是從 json 中提取所有嵌套屬性的另一種解決方案
import json
result_set = set([])
def parse_json_array(json_obj, parent_path):
array_obj = list(json_obj)
for i in range(0, len(array_obj)):
json_ob = array_obj[i]
if type(json_obj) == type(json_obj):
parse_json(json_ob, parent_path)
return None
def parse_json(json_obj, parent_path):
for key in json_obj.keys():
key_value = json_obj.get(key)
# if isinstance(a, dict):
if type(key_value) == type(json_obj):
parse_json(key_value, str(key) if parent_path == "" else parent_path + "." + str(key))
elif type(key_value) == type(list(json_obj)):
parse_json_array(key_value, str(key) if parent_path == "" else parent_path + "." + str(key))
result_set.add((parent_path + "." + key).encode('ascii', 'ignore'))
return None
file_name = "C:/input/sample.json"
file_data = open(file_name, "r")
json_data = json.load(file_data)
print json_data
parse_json(json_data, "")
print list(result_set)
輸出:
{u'states': {u'state': u'Tamil Nadu', u'cities': [{u'city': u'Chennai'}, {u'city': u'Coimbatore'}]}, u'id': u'1', u'salaries': [{u'salary': u'1000'}, {u'salary': u'5000'}], u'name': u'a'}
['states.cities.city', 'states.cities', '.id', 'states.state', 'salaries.salary', '.salaries', '.states', '.name']
筆記:
My Python version: 2.7
你也可以這樣做。
data = { "id":"1", "name":"a", "salaries":[ { "salary":"1000" }, { "salary":"5000" } ], "states":{ "state":"Karnataka", "cities":[ { "city":"Bangalore" }, { "city":"Mysore" } ], "state":"Tamil Nadu", "cities":[ { "city":"Chennai" }, { "city":"Coimbatore" } ] } }
def dict_ittr(lin,data):
for k, v in data.items():
if type(v)is list:
for l in v:
dict_ittr(lin+"."+k,l)
elif type(v)is dict:
dict_ittr(lin+"."+k,v)
pass
else:
print lin+"."+k
dict_ittr("",data)
輸出
.states.state
.states.cities.city
.states.cities.city
.id
.salaries.salary
.salaries.salary
.name
如果您將 json 視為 python 字典,這應該可以工作。
我剛剛寫了一個簡單的遞歸程序。
腳本
import json
def js_r(filename):
with open(filename) as f_in:
return(json.load(f_in))
g = js_r("city.json")
answer_d = {}
def base_line(g, answer_d):
for key in g.keys():
answer_d[key] = {}
return answer_d
answer_d = base_line(g, answer_d)
def recurser_func(g, answer_d):
for k in g.keys():
if type(g[k]) == type([]): #If the value is a list
answer_d[k] = {list(g[k][0].keys())[0]:{}}
if type(g[k]) == type({}): #If the value is a dictionary
answer_d[k] = {list(g[k].keys())[0]: {}} #set key equal to
answer_d[k] = recurser_func(g[k], answer_d[k])
return answer_d
recurser_func(g,answer_d)
def printer_func(answer_d, list_to_print, parent):
for k in answer_d.keys():
if len(answer_d[k].keys()) == 1:
list_to_print.append(parent)
list_to_print[-1] += k
list_to_print[-1] += "." + str(list(answer_d[k].keys())[0])
if len(answer_d[k].keys()) == 0:
list_to_print.append(parent)
list_to_print[-1] += k
if len(answer_d[k].keys()) > 1:
printer_func(answer_d[k], list_to_print, k + ".")
return list_to_print
l = printer_func(answer_d, [], "")
final = " ".join(l)
print(final)
解釋
base_line
制作了一個包含所有基本鍵的字典。
recursur_func
檢查鍵的值是列表還是字典,然后根據需要添加到答案字典中,直到answer_d
看起來像: {'id': {}, 'name': {}, 'salaries': {'salary': {}}, 'states': {'state': {}, 'cities': {'city': {}}}}
在調用這兩個函數之后,您在某種意義上擁有了一個鍵字典。 然后 printer_func 是一個遞歸函數,可以根據需要打印它。
筆記:
您的問題與此類似: 獲取嵌套字典的所有鍵,但由於您有一個嵌套列表/字典而不僅僅是一個嵌套字典,因此他們的答案對您不起作用,但有關該主題的討論更多詢問您是否需要更多信息
編輯 1
我的 python 版本是 3.7.1
我在頂部添加了一個 json 文件打開器。 我假設 json 名為 city.json 並且位於同一目錄中
編輯 2:更徹底的解釋
我發現處理數據的主要困難在於您可以擁有無限嵌套的列表和字典。 這使它變得復雜。 由於它是無限可能的嵌套,因此我認為這是一個遞歸問題。
所以,我建立了一個字典,代表您正在尋找的關鍵結構。 首先,我從基線開始。
base_line
使{'id': {}, 'name': {}, 'salaries': {}, 'states': {}}
這是一個空字典的字典。 我知道,當你打印。 每個關鍵結構(如states.state
)都以這些詞之一開頭。
遞歸
然后我使用recursur_func
添加所有子鍵。 當給定字典g
此函數 for 循環遍歷該字典中的所有鍵,並且(假設answer_d
具有g
具有的每個鍵),每個鍵都會將該鍵的子項添加到 answer_d。
如果孩子是一本字典。 然后我遞歸使用給定的字典g
現在是與孩子有關的字典的子部分,而 answer_d 是與孩子有關的 answer_d 的子部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.