How do you parse a specific key to multiple rows and column from a response?
I am getting a response:
response = requests.post('https://api.kewords.com/v1/get_keyword_data', data=my_data, headers=my_headers)
which returns:
{
"data": {
"heart disease": {
"vol": 18100,
"cpc": {
"currency": "$",
"value": "2.01"
},
"keyword": "keyword planner",
"competition": 0.21,
"trend": [
{
"month": "January",
"year": 2022,
"value": 18100
},
{
"month": "February",
"year": 2022,
However, when I normalize it before I save it to a .csv, it places everything into a single row:
How do you parse a specific field, like data.heart disease.trend in my example, with separate columns for year and month based on value to a pandas dataframe? Every method from normalizing it to dealing with it as a dict has failed.
my code:
my_data = {
'country': 'us',
'currency': 'USD',
'dataSource': 'cli',
f'kw[{keyword}]': ["keywords tool", "keyword planner"]
}
my_headers = {
'Accept': 'application/json',
'Authorization': ''
}
response = requests.post('https://api.keywords.com/v1/get_keyword_data', data=my_data, headers=my_headers)
#write to json
with open('output.json', 'wb') as outf:
outf.write(response.content)
if response.status_code == 200:
print('success\n\n', response.content.decode('utf-8'))
else:
print("An error occurred\n\n", response.content.decode('utf-8'))
Using json_normalize:
data = json.loads(response.text)
df = pd.json_normalize(
data=data["data"]["heart disease"],
meta=["vol", "keyword", "competition", "cpc"],
record_path="trend"
)
df = pd.concat([df.drop(["cpc"], axis=1), df["cpc"].apply(pd.Series)], axis=1)
print(df)
Output:
month year value vol keyword competition currency value
0 January 2022 18100 18100 keyword planner 0.21 $ 2.01
1 February 2022 20000 18100 keyword planner 0.21 $ 2.01
I am trying to extract the values which key equal Name in a key:value pair that i extracted from an API. I am using the following formula;
final List<String> namesList =list.map((e) => e["Name"].toString()).toList();
print(namesList);
I can extract the values of name keys, however it is extracted as JSArray. I couldn't extract them as string.
Result: [Name1, Name2] JSArray
Should be: ["Name1", "Name2"] List
Thank you.
Please refer to below code
void main() {
List list = [
{"code": "ABC", "Name": "\"Name1\"", "Type": "1"},
{"code": "DEF", "Name": "\"Name2\"", "Type": "2"}
];
final List<String> nameList = list.map((e) => e["Name"].toString()).toList();
print(nameList);
List list1 = [
{"code": "ABC", "Name": "Name1", "Type": "1"},
{"code": "DEF", "Name": "Name2", "Type": "2"}
];
final List<String> nameList1 =
list1.map((e) => '"${e["Name"].toString()}"').toList();
print(nameList1);
}
// Result
// ["Name1", "Name2"]
It seems that nameList element type is String.
The 'print' result only is shown remove double quotation marks.
Or you really want to make a list with double quotation marks.
void main() {
List list = [{'Code': 'ABC', 'Name': 'Name1', 'Type': '1'}, {'Code': 'DEF', 'Name': 'Name1', 'Type': '2'}];
final List<String> namesList =list.map<String>((e) => "\"${e["Name"]}\"").toList();
print(namesList);
print(namesList[0].runtimeType);
}
This is how far I've gotten from converting a pandas dataframe into the format I want it.
print(data_frame)
Output:
>>{'Country': ['Croatia', 'Serbia', 'United States', 'Algeria', 'Chile'],
'Value': [5, 5, 4, 2, 2]}
dictlist = []
for key, value in data_frame.items():
temp = [key,value]
dictlist.append(temp)
print(dictlist)
Output:
>>[['Country', ['Croatia', 'Serbia', 'United States', 'Algeria', 'Chile']], ['Value', [5, 5, 4, 2, 2]]]
Now here is where I'm lost. I've tried so many combinations of videos and tutorials that even my brute force ideas are empty.
for key, val in dictlist:
print(key, "->", val)
for item in val:
print(item)
output:
>>Country -> ['Croatia', 'Serbia', 'United States', 'Algeria', 'Chile']
>>Croatia
>>Serbia
>>United States
>>Algeria
>>Chile
>>Value -> [5, 5, 4, 2, 2]
>>5
>>5
>>4
>>2
>>2
I just don't know how to work inside that for loop. I can't iterate any further than that.
This is the format I'm trying to get it converted to:
[
{
"name": "Croatia",
"value": 5,
},
{
"name": "Serbia",
"value": 5,
},
{
"name": "United States",
"value": 4,
},
{
"name": "Algeria",
"value": 2,
},
{
"name": "Chile",
"value": 2,
}
]
Update
Thanks to a friendly fellow in the chat, I've now gotten closer to the goal. This line helped me a lot.
data_frame = frame.set_index('Country').T.to_dict('list')
print(data_frame)
output:
{'Croatia': [5],
'Serbia': [5],
'United States': [4],
'Algeria': [2],
'Chile': [2]}
Not sure why the values got converted into arrays, but at least this should be solvable! Cheers!
This would return dictionary as desired in the question.
# this is the data frame
frame = pd.DataFrame({'Country': ['Croatia', 'Serbia', 'United States', 'Algeria', 'Chile'],
Check the pandas documentation for to_dict to get available parameter options apart from 'list' that was used in the posted code sample.
Now one can settle for 'records' which returns dictionary inside a list:
data_frame = frame.set_index('Country')T.to_dict('records')[0]
# this is the output without [0]
# [{'Croatia': 5, 'Serbia': 5, 'United States': 4, 'Algeria': 2, 'Chile': 2}]
# so you need the [0] to pick the dictionary in the list and get the desired dictionary output.
I have some data in the following variables,
want to store the python dictionary in the following JSON format,
{
'name': {
'Address': '123 abc, IN, 50012',
'Phone': '123456',
},
'name2': {
'Address': '123 abc, IN, 50012',
'Phone': '123456',
},
}
Updated JSON format(Required in this format)
{
"name":[
{"Address": "123 abc, IN, 50012"},
{"Phone": "123456"}
],
"name2": [
{"Address": "123 abc, IN, 50012"},
{"Phone": "123456"}
]
}
But I managed only to get the JSON in this format,
{"phone": "123456738", "address": "address1,", "name": "name1"}
{"phone": "123456178", "address": "address2,", "name": "name2"}
{"phone": "123452678", "address": "address3,", "name": "name3"}
below is my code
#getting data and adding to dict
dict_list = []
for data in all_data:
dict = {}
dict["phone"] = phone.strip()
dict["address"] = address.strip()
dict["name"] = name.strip()
dict_list.append(dict)
#writing to json file
with open('data.json', 'w') as outfile:
for details in dict_list:
r = json.dumps(details)
loaded_r = json.loads(r)
json.dump(loaded_r, outfile)
you want to convert the inner dictionary to a list of dictionaries containing only one key & value. Doable with some comprehension syntax:
in_dict = {
'name': {
'Address': '123 abc, IN, 50012',
'Phone': '123456',
},
'name2': {
'Address': '123 abc, IN, 50012',
'Phone': '123456',
},
}
out_dict = {k : [{k2:v2} for k2,v2 in v.items()] for k,v in in_dict.items()}
For each key,value (dictionary) pair, iterate on items of the sub-dict and create 1 dictionary per key,value in a list.
result:
>>> out_dict
{'name': [{'Address': '123 abc, IN, 50012'}, {'Phone': '123456'}],
'name2': [{'Address': '123 abc, IN, 50012'}, {'Phone': '123456'}]}
I tried to use jqGrid formatter: "actions" for remote json url but it shifts rows because number of column names and actual returned data doesn't match (act column is extra one in column names). I did search online and it looks like all examples are for local data (on page) where json is used as key/value, while url:somepage.php returns a csv kind-of-format of columns(no keys, just values). Also I use id as hidden field, while all examples show id. I use one more hidden column as well.
here is my colmodel:
url: "manager_json",
editurl: "manager_edit",
datatype: "json",
//data: mydata,
width:1000,
//jsonReader: {
// repeatitems : false,
// },
colNames: ["","Id","Uid","Custom Id","Image Name","Coord. X","Coord. Y","Gender","Progress","Status","Created","Updated"],
colModel: [{"name":"act","template":"actions","formatoptions":{"editformbutton":true}},{"name":"id","align":"center","width":33,"editable":false,"hidden":true},{"name":"uid","align":"center","width":33,"editable":true,"hidden":true,"editrules":{"edithidden":false,"required":false}},{"name":"ta_id","align":"center","width":100,"editrules":{"required":true}},{"name":"image","width":150,"template":"text","editrules":{"required":true}},{"name":"x","width":100,"align":"center","template":"integer","editrules":{"required":true}},{"name":"y","width":100,"align":"center","template":"integer","editrules":{"required":true}},{"name":"gender","width":100,"align":"center","formatter":"select","stype":"select","editrules":{"required":true},"edittype":"select","editoptions":{"value":"f:Female;m:Male","defaultValue":"m"},"searchoptions":{"sopt":["eq","ne"],"value":":Any;f:Female;m:Male"}},{"name":"progress","width":120,"align":"center","formatter":"select","stype":"select","editrules":{"required":true},"editable":false,"edittype":"select","editoptions":{"value":"-:New;pf:Process Failed;ps:Process Scheduled;pss:Process Success;p:Processing...;s:Staging;tf:Test Failed;ts:Test Scheduled;tss:Test Success;t:Testing...","defaultValue":"m"},"searchoptions":{"sopt":["eq","ne"],"value":":Any;-:New;pf:Process Failed;ps:Process Scheduled;pss:Process Success;p:Processing...;s:Staging;tf:Test Failed;ts:Test Scheduled;tss:Test Success;t:Testing..."}},{"name":"status","width":100,"align":"center","formatter":"select","stype":"select","edittype":"select","editoptions":{"value":"a:Active;n:New","defaultValue":"m"},"searchoptions":{"sopt":["eq","ne"],"value":":Any;a:Active;n:New"}},{"name":"date_created","width":150,"template":"text","editable":false},{"name":"last_updated","width":150,"template":"text","editable":false}]
And here is my actual data from my server (db) as per jqgrid specification:
{"page":1,"total":1,"records":7,"rows":[{"id":32,"cell":[32,"889daf31ff3e49544f52850258439600","2uu","2ok",2,2,"m","-","a","2017-02-10 18:57:05","2017-02-10 23:37:12"]},{"id":30,"cell":[30,"","11","11",1,1,"m","-","a","2017-02-10 18:01:52","2017-02-10 18:01:52"]},{"id":29,"cell":[29,"aaa","ww222111uu","11",1,1,"m","-","a","2017-02-10 18:00:36","2017-02-10 23:37:08"]},{"id":27,"cell":[27,"","11","1",1,1,"m","-","a","2017-02-10 17:57:41","2017-02-10 17:57:41"]},{"id":25,"cell":[25,"","4tt","4img",4,4,"f","-","n","2017-02-10 17:50:21","2017-02-11 00:26:03"]},{"id":24,"cell":[24,"","1","1",1,1,"m","-","a","2017-02-10 17:49:38","2017-02-10 17:49:38"]},{"id":22,"cell":[22,"","bbb","imam 222",2,22,"f","p","n","2017-02-08 20:14:55","2017-02-10 13:27:57"]}]}
As you can see cell row has less columns than colNames and colModel. Also id and uid columns are hidden. I added on extra fake column from db, but it did not help
i am using jqGrid 4.13.7-pre
I'd recommend you to return objects like
{
"id": 32,
"uid": "889daf31ff3e49544f52850258439600",
"ta_id": "2uu",
"image": "2ok",
"x": 2,
"y": 2,
"gender": "m",
"progress": "-",
"status": "a",
"date_created": "2017-02-10 18:57:05",
"last_updated": "2017-02-10 23:37:12"
}
instead of
{
"id": 32,
"cell": [
32, "889daf31ff3e49544f52850258439600", "2uu", "2ok", 2, 2, "m", "-", "a",
"2017-02-10 18:57:05", "2017-02-10 23:37:12"
]
}
as the server response. It will simplify your code.
If you do need to process the current format of the data, then you will have to force repeatitems: false mode by usage the option
jsonReader: {
repeatitems: false
}
and to use jsonmap property of colModel to inform jqGrid from which element of the item one should read the column data. The jsonmap could be either in the string form like
jsonmap: "cell.1"
or in the function form:
jsonmap: function (item) {
return item.cell[1];
}
To make the code better maintainable you can define an object like
var columnOrder = {
id: 0,
uid: 1,
ta_id: 2,
image: 3,
x: 4,
y: 5,
gender: 6,
progress: 7,
status: 8,
date_created: 9,
last_updated: 10
};
which provides the index in cell array by the column name and to use jsonmap like
jsonmap: function (item) {
return item.cell[columnOrder.uid];
}
The demo https://jsfiddle.net/OlegKi/ozzgnaeh/2/ demonstrates the approach.