Couple of quick things. The function you posted has an extra space in 'box' entry of the fields
list, and in python the with
keyword will automatically close a file for you. No need to do it explicitly.
I have tested this on my machine, running Python 3.6. I included a duplicate in the list because I assume your data has more than a single output list? If not it shouldn't make a difference.
Are you sure the following code doesn't work?
import csv
data = [{'box': [277, 90, 48, 63],
'confidence': 0.99,
'keypoints': {
'left_eye': (291, 117),
'right_eye': (314, 114),
'nose': (303, 131),
'mouth_left': (296, 143),
'mouth_right': (313, 141)}
},
{'box': [277, 90, 48, 63],
'confidence': 0.99,
'keypoints': {
'left_eye': (291, 117),
'right_eye': (314, 114),
'nose': (303, 131),
'mouth_left': (296, 143),
'mouth_right': (313, 141)}
}
]
# Write to csv
with open('data.csv', 'w') as f:
fields = ['box', 'confidence', 'keypoints']
w = csv.DictWriter(f, fieldnames=fields)
w.writeheader()
w.writerows(data)
# Append to existing csv
with open('data.csv', 'a') as f:
fields = ['box', 'confidence', 'keypoints']
w = csv.DictWriter(f, fieldnames=fields)
w.writerows(data)
With the output:
box,confidence,keypoints
"[277, 90, 48, 63]",0.99,"{'left_eye': (291, 117), 'right_eye': (314, 114), 'nose': (303, 131), 'mouth_left': (296, 143), 'mouth_right': (313, 141)}"
"[277, 90, 48, 63]",0.99,"{'left_eye': (291, 117), 'right_eye': (314, 114), 'nose': (303, 131), 'mouth_left': (296, 143), 'mouth_right': (313, 141)}"
What the output looks like in LibreCalc
If you want the keys of keypoints in their own columns:
import csv
data = [{'box': [277, 90, 48, 63],
'confidence': 0.99,
'keypoints': {
'left_eye': (291, 117),
'right_eye': (314, 114),
'nose': (303, 131),
'mouth_left': (296, 143),
'mouth_right': (313, 141)}
},
{'box': [277, 90, 48, 63],
'confidence': 0.99,
'keypoints': {
'left_eye': (291, 117),
'right_eye': (314, 114),
'nose': (303, 131),
'mouth_left': (296, 143),
'mouth_right': (313, 141)}
}
]
with open('data2.csv', 'w') as f:
# get a list of the keys in the values of 'keypoints' key
kps = data[0].get('keypoints').keys()
# make the list for the fieldnames, * just expands a list to its components
fields = ['box', 'confidence', *kps]
w = csv.DictWriter(f, fieldnames=fields)
w.writeheader()
out_dict = {}
# Loop over however many data dictionaries are in the list data
for data_dict in data:
# Loop over keys and values in the dictionary
for k, v in data_dict.items():
if k != 'keypoints':
out_dict.update({k: v})
elif k == 'keypoints':
# Loop over the keys that correspond to 'keypoints' key
for k2, v2 in data_dict['keypoints'].items():
out_dict.update({k2: v2})
# Write the created out dictionary to the file
w.writerow(out_dict)
# Appending to an already existing csv
with open('data2.csv', 'a') as f:
kps = data[0].get('keypoints').keys()
# make the list for the fieldnames, * just expands a list to its components
fields = ['box', 'confidence', *kps]
w = csv.DictWriter(f, fieldnames=fields)
out_dict = {}
# Loop over however many data dictionaries are in the list data
for data_dict in data:
# Loop over keys and values in the dictionary
for k, v in data_dict.items():
if k != 'keypoints':
out_dict.update({k: v})
elif k == 'keypoints':
# Loop over the keys that correspond to 'keypoints' key
for k2, v2 in data_dict['keypoints'].items():
out_dict.update({k2: v2})
# Write the created out dictionary to the file
w.writerow(out_dict)
With this output:
box,confidence,left_eye,right_eye,nose,mouth_left,mouth_right
"[277, 90, 48, 63]",0.99,"(291, 117)","(314, 114)","(303, 131)","(296, 143)","(313, 141)"
"[277, 90, 48, 63]",0.99,"(291, 117)","(314, 114)","(303, 131)","(296, 143)","(313, 141)"
flattened output in LibreCalc
This second function is effectively the same as flattening a json as one of the other answers mentioned, just without a dependency.