How to plot data from JSON Structure array
古いコメントを表示
Hi
I have used HTTP to download a large amount structued data from an API.
This is my code
function n02()
downloaded_data = device_data("864475047548549","2022-04-08T10:31:00Z","2022-05-08T11:31:00Z");
%struct2table(downloaded_data)
plot(downloaded_data.Timestamp,downloaded_data.iot_battery);
end
This is the output i am getting
Error using plot
Invalid first data argument.
Error in n02 (line 6)
plot(x,y);
What am i doing wrong
採用された回答
その他の回答 (3 件)
Dharmesh Joshi
2022 年 5 月 9 日
12 件のコメント
Looking more carefully, I see now that you have a function, device_data, that returns some data. Is this data in json format or is it already a structure. I can't tell enough from what you show to help you further. If you could please attach a small self contained (one that I can run) example of what you are trying to do that demonstrates the problem you are having then I might be able to give you more help.
Regarding why it might work with the square brackets, it seems like you may have data that is in a comma separated list, so putting it in square brackets turns it into an array that can be plotted.
Dharmesh Joshi
2022 年 5 月 9 日
If you can't provide a runnable example to show the problem, then lets go back to your attempt to plot the two variables, downloaded_data.Timestamp,downloaded_data.iot_battery.
Please show the first few elements of downloaded_data.Timestamp, and downloaded_data.iot_battery so that I can see exactly what you are trying to plot.
Dharmesh Joshi
2022 年 5 月 9 日
Dharmesh Joshi
2022 年 5 月 9 日
Jon
2022 年 5 月 9 日
OK I'm starting to understand. Here is an approach:
% make up a little bit of example data just to show how to manipulate it
downloaded_data(1).Timestamp = '2022-05-08T11:30:47.7909324+00:00';
downloaded_data(2).Timestamp = '2022-05-08T11:40:27.4909628+00:00';
downloaded_data(3).Timestamp = '2022-05-08T11:50:36.2309354+00:00';
downloaded_data(1).iot_battery = 100;
downloaded_data(2).iot_battery = 104;
downloaded_data(3).iot_battery = 305;
% get values from array of structures to arrays
TimeStampRaw = {downloaded_data.Timestamp}; % cell array of character arrays
iot_battery = [downloaded_data.iot_battery] % array of doubles
% need to clean up time stamps, get rid of letter T in middle and +00:00 at
% end, use cellfun to perform operation on every element in the cell array
TimeStamp = cellfun(@(x)[x(1:10),' ',x(12:27)],...
TimeStampRaw,'uniformOutput',false);
% convert TimeStamp strings to datetime array
t = datetime(TimeStamp)
% plot result
plot(t,iot_battery)
Dharmesh Joshi
2022 年 5 月 10 日
Jon
2022 年 5 月 10 日
OK Good luck, let me know how it goes
Dharmesh Joshi
2022 年 5 月 11 日
Yes, the problem here is again that when accessing one field, in this case .iot_temperture, in an array of structures, in this case, downloaded_data, you must first turn the comma separated list into a vector. You do this by surrounding it with square brackets.
You also have a lot of unecessary round parenthesis.
So, modify your code above to:
iot_temperture=[downloaded_data.iot_temperture]/65536*165-40;
One editorial comment, I like your use of meaningful names for your variables, but you might want to rename your field .iot_temperture to .iot_temperature. That is, correct the spelling of temperature
Dharmesh Joshi
2022 年 5 月 11 日
Jon
2022 年 5 月 11 日
The blank spots probably correspond to points where the temperature value is nan (not a number), so as you say missing data.
Dharmesh Joshi
2022 年 5 月 11 日
11 件のコメント
Dharmesh Joshi
2022 年 5 月 11 日
The error you report above is just due to some problem in the formating of the text for your y axis in the plot command.
Do you know how to use the debugging tools?
If so you could set a breakpoint just before the call to plot the data and then you could look at the contents of iot_temperture
Alternatively you can just temporarily modify your code to remove the semicolon at end of the line where iot_temperature is calculated (as shown below) and you will see the values on your screen.
iot_temperture=[downloaded_data.iot_temperture]/65536*165-40 % remove semicolon to see output
If you don't know how to use the debugger, it is really an essential tool, here's an intro https://www.mathworks.com/help/matlab/matlab_prog/debugging-process-and-features.html
Finally, if you are still revising the program, you may want to change your variable names to correctly spell temperature. Currently you have variables/fields such as downloaded_data.iot_temperture, for me it would be nicer if that were correctly spelled (doesn't affect the calculation just better style) as downloaded_data.iot.temperature
Dharmesh Joshi
2022 年 5 月 11 日
Jon
2022 年 5 月 11 日
If you just wanted to know if there were any nan values in iot_temperture, you could insert this line just before you plot
disp(any(isnan(iot_temperture)))
If you have nan's then before the data is plotted you will see a 1 displayed on your console
Dharmesh Joshi
2022 年 5 月 11 日
Dharmesh Joshi
2022 年 5 月 11 日
Dharmesh Joshi
2022 年 5 月 11 日
Jon
2022 年 5 月 12 日
I don't think there is a limit to how many points can be plotted.
You may also have missing values in your plot if there are "not a time" values in the time vector. You can determine if there are any of these using the isnat function. So in a similar way as you checked if there were any nan values in the temperature vector you could check if there are any not a time values in the datetime vector using
iot_temperture=[downloaded_data.iot_temperture]/65536*165-40;
disp(any(isnat(t)))
plot(t,iot_temperature)
You will see a 1 displayed if there are any not a time values, othererwise it will display a zero.
To go further I strongly suggest you learn how to use the debug tool to set a breakpoint just before the plot and then you can look directly at the contents of those variables just before they are plotted.
Dharmesh Joshi
2022 年 5 月 12 日
編集済み: Dharmesh Joshi
2022 年 5 月 12 日
Great job isolating the problem!
It looks like, for whatever reason, the raw date strings sometimes have less decimal places. So, the + character appears sooner. Cutting of at character 27 can therefore sometimes include a + in the string which leads to the NaT.
You could just try using one less decimal place and modify to
TimeStamp = cellfun(@(x)[x(1:10),' ',x(12:26)],...
TimeStampRaw,'uniformOutput',false);
You could also take a more robust approach and make a little function to clean up the strings like this:
...
% end, use cellfun to perform operation on every element in the cell array
TimeStamp = cellfun(@(x)cleanTime(x),...
TimeStampRaw,'uniformOutput',false);
% convert TimeStamp strings to datetime array
t = datetime(TimeStamp)
% plot result
plot(t,iot_battery)
% put function to clean the time stamps at end of script, or nested inside of your main function
function tstmp = cleanTime(str)
% clean up time stamps, get rid of letter T in middle and +00:00 at
% end
parts = strsplit(str,{'T','+'});
tstmp = [parts{1},' ',parts{2}];
end
Dharmesh Joshi
2022 年 5 月 12 日
編集済み: Dharmesh Joshi
2022 年 5 月 12 日
Dharmesh Joshi
2022 年 5 月 14 日
0 投票
1 件のコメント
That's great to hear.
I think to keep this thread clear it would be good to accept my answer rather than accepting your own final note (which should probably just be another comment) as an answer. I think it is possible to modify which answer you accept.
Rather than starting up a new thread here I will anwer your question regarding the grouping of data as a further comment under my original answer
カテゴリ
ヘルプ センター および File Exchange で Data Type Identification についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
