I'm importing data from Excel to MATLAB. My data in Excel is in [h]:mm:ss format, but when after importing to MATLABthe data becomes a decimal number.
Is there a way to convert this data back to an [h]:mm:ss format in MATLAB?
Some examples:
21:45:05 equals 0.906307870370370
21:14:31 equals 0.885081018518519
213:17:56 equals 8.88745370370370
I understand the conversion being a multiple of 24h be it in seconds, minuites or hours - which would imply 12:00:00 = 0.5. But I don't understand how I could convert the data back, i.e. 0.75 becomes 18:00:00 etc?
I've tried New_Nun(i,j) = datestr(nun(i,j),'HH:MM:SS'); to do this conversion, but I get this error -
Unable to perform assignment because the indices on the left side are not compatible with the size of the right side.
Would this be because my nun variable has NaN's in?
Note that datestr outputs a string, while the New_Nun(i,j)=...assignment expects a single value.
datestr(nun(i,j),'HH:MM:SS') outputs a [8 x 1] char array, which will not fit into New_Nun(i,j). And, by the way, 'HH:MM:SS' is indeed the correct argument for hours, minutes and seconds.
You may rather use a cell for New_Nun, which can contain any kind of data including strings of arbitrary length :
%Initialize random values with a NaN
nun=rand([5 5]);
nun(2,5)=NaN;
New_Nun = cell(size(nun)); %Initialize the cell array
not_a_nan = ~isnan(nun); %Selection valid values
New_Nun(not_a_nan) = cellstr(datestr(nun(not_a_nan),'HH:MM:SS')); %Fill the cell array
disp(New_Nun)
'13:47:28' '23:37:19' '06:00:28' '13:24:09' '12:38:05'
'00:55:58' '08:34:58' '04:25:44' '11:14:46' []
'13:17:25' '10:34:02' '11:17:16' '04:42:18' '05:51:32'
'20:40:44' '18:30:16' '04:29:22' '17:43:03' '22:05:24'
'16:36:35' '10:17:18' '22:45:41' '16:04:17' '07:06:39'
The NaN value has been converted to an empty cell. It could be replaced with any default value, e.g. New_Nun(~not_a_nan)={'00:00:00'};
This code does not handle hours above 24, as datestr. For than, hours need to be treated separately.
%Initialize random values with a NaN and one value larger than 24h
nun=rand([5 5]);
nun(2,5)=NaN;
nun(3,4)=nun(3,4)+10; % One value above 24h
New_Nun = cell(size(nun)); %Initialize the cell array
not_a_nan = ~isnan(nun); %Selection valid values
mmss = cellstr(datestr(nun(not_a_nan),'MM:SS')); %Write only MM:SS
hh = floor(nun(not_a_nan(:))*24); %Get hours, and make it a column vector
%Now, add the hours
hours_not_zero = hh~=0; % Optional: used to display mm:ss if hh=0
mmss(hours_not_zero) = cellfun(#(h,m) sprintf('%02d:%s',h,m),num2cell(hh(hours_not_zero)),mmss(hours_not_zero),'uniformoutput',false);
New_Nun(not_a_nan) = mmss;
disp(New_Nun)
'02:53:42' '08:38:56' '12:07:03' '15:28:54' '12:49:18'
'16:21:15' '03:44:23' '01:22:31' '20:43' []
'02:36:04' '11:08:51' '19:51:35' '244:45:48' '33:55'
'16:14:08' '08:04:01' '12:27:22' '08:17:48' '06:16:15'
'10:41:08' '03:16:19' '04:47:15' '04:33:37' '20:36:42'
This time, the value 35:34:11 is represented correctly. Not significant hours are not displayed, such as '20:43' for '00:20:43'.
Related
The excel column contains Zulu Timzezones How to calculate the difference between two dates in seconds.milliseconds
From Time 2022-04-25T04:16:57.823121842Z
To Time
2022-04-25T04:16:58.173194593Z
2022-04-25T04:16:58.089133751Z
2022-04-25T04:16:58.462278784Z
2022-04-25T04:16:57.829376293Z
2022-04-25T04:16:57.961790312Z
2022-04-25T04:16:58.445884586Z
2022-04-25T04:16:57.830806273Z
2022-04-25T04:16:58.067723338Z
2022-04-25T04:16:58.470913276Z
2022-04-25T04:16:57.838787068Z
When I Try to Do something like =B13-B14
Error
Function MINUS parameter 1 expects number values. But '2022-04-25T04:35:59.092943356Z' is a text and cannot be coerced to a number.
Converted to Number format
REVISED: I forgot to convert the milliseconds
You can convert the date strings into time values by breaking them into parts:
=DATEVALUE(LEFT(A2,10)) + TIMEVALUE( MID(A2,12,8) ) --MID(A2,20,10)/24/60/60
Where A2 is the date string.
This assumes that they have the exact structure that you have shown and fully padded with zeros. If that is not the case, for example the milliseconds could be .095Z, then you can mod this to:
=DATEVALUE(LEFT(A2,10)) + TIMEVALUE( MID(A2,12,8) ) --MID(SUBSTITUTE(A2,"Z",""),20,999)/24/60/60
to be safe.
Somewhat simple problem:
I need to turn a column A, which contains numbers with up to 1 decimal (20, 142, 2.5, etc.) to a string with a specific format, namely 8 whole digits and 6 decimal digits but without the actual decimal period, like so:
1 = 00000001000000
13 = 00000013000000
125 = 00000125000000
46.5 = 00000046500000
For what it's worth, the input data from column A will never be more than 3 total digits (0.5 to 999) and the decimal will always be either none or .5.
I also need for Excel to leave the zeroes alone instead of auto-formatting as a number and removing the ones at the beginning of the string.
As a makeshift solution, I've been using =CONCATENATE("'",TEXT(A1,"00000000.000000")), then copying the returning value and "pasting as value" where I actually need it.
It works fine, but I was wondering if there was a more direct solution where I don't have to manually intervene.
Thanks in advance!
=TEXT(A1*1000000,"0000000000000") I think that's what you mean.
I have data of 100 x 101. I want to convert them in series e.g. for first row all column data then for 2nd row all column data and so on. It means the result will be three columns only. The first column with row numbers, the 2nd column with column numbers and the 3rd column with the value for that respective row and column.
Could you please help me doing this conversion in MATLAB.
Available data are in ASCII format and it is possible to open in both MATLAB and Excel.
This can be done by find:
A = rand(100,101);
[data(:,1), data(:,2), data(:,3)] = find(A);
data = sortrows(data,[1 2]);
Note that this is highly inefficient, as you are storing 3 values where you only need to store 1 (the element's actual value). For accessing a specific element, say row 31, column 43, you simply do A(31,43), where you index the matrix.
The file size of data is indeed three times larger than that of A:
whos
Name Size Bytes Class Attributes
A 100x101 80800 double
data 10100x3 242400 double
You can use the ind2sub function that is faster and make more sense in this situation:
tic
A = rand(100,101);
[data(:,1), data(:,2), data(:,3)] = find(A);
data = sortrows(data,[1 2]);
toc
tic
B = A' ;
[data_B(:,1), data_B(:,2)] = ind2sub(size(B), 1:length(B(:)));
data_B(:,3) = B(:);
toc
The output for the timing is as follow:
Elapsed time is 0.002130 seconds (first method)
Elapsed time is 0.000525 seconds (second method).
I am having Excel with Date time stamp at random row in B Column,
Ex: Where in between cell are Empty ( B2, B3..etc).
B1 : 15:13:48:335 2014/08/06
B27: 15:13:55:955 2014/08/06
B31: 15:14:16:005 2014/08/06 ...
I need to find the time difference between 2 consecutive entries Ex: B21-B1 and B31-B27 and so on.
If the values you've shown are actual datetimes, then they are numbers that seem to grow progressively larger as the rows increase.
To get the difference from B1 to B27,
=LARGE(B:B, 2)-LARGE(B:B, 3)
Format the result as time in any way you prefer.
For the difference from B27 to B31,
=LARGE(B:B, 1)-LARGE(B:B, 2)
When datetimes are actual datetimes and not text, the LARGE function can be used just like any other number.
If your values in column B are text, start by reverting them to proper datetimes. Use something like the following,
=DATEVALUE(RIGHT(B1, 5)&"/"&MID(B1, 14, 4))+TIMEVALUE(LEFT(B1, 8)&"."&MID(B1, 10,3))
Correct your data first; then worry about manipulating the numbers.
If the cells propreties are correct, Excel should be able do compute a difference between them without any problem.
Both of the cells containing the dates must be set with Date/Hour format, the cell containing the result of the difference can be (for instance) set to Standard. Then the difference will be a number (integer or float). For instance :
If the result is 3, it means 3 days, multiply it by 24 to have the
number of hours.
If the result is 3,6667, the integer part gives you
the number of full days, the float part gives you the number of
hours. 0.6667*24 = 16 hours.
Hope it helped
I was retrieving data from Bloomberg using Matlab history function and it seems that Matlab set 4 decimal places to be the default. This is sometimes inconsistent with the data that I pulled from Excel. For example:
Here's the Matlab code:
[d, sec] = history(c, 'TY1 Comdty', 'PX_LAST', '1982-5-6', '1982-5-6')
I get different results from Matlab and Excel:
Date 5/6/1982
Excel 72.96875
Matlab 72.9688
Is there a way to set the property of history function and get 72.96875 instead of 72.9688?
There is no solution as good as Excel has for displaying number with the desired format.
In Matlab, you can set the format long to have 15 decimal places, and format short to have 4 decimal places. That's all you have.
Nevertheless, two workarounds. The first uses round
(1) format long %define 15 digit precision
xround = #(x,d) round(x/d)*d; %rounding function with d format
a = xround(72.96875, 0.00001) %rounding your value by calling 'xround' function
It gives
a = 72.968750000000000
The second workaround prints a string (not a scalar)
(2) sprintf('%.5f', 72.96875)
It gives
ans = 72.96875
To match Excel with Matlab, you can type
[d, sec] = history(c, 'TY1 Comdty', 'PX_LAST', '1982-5-6', '1982-5-6');
d = xround(d, 0.00001);
Use the format command to set the display to the desired number of significant digits: http://www.mathworks.co.uk/help/matlab/ref/format.html