I'm running a fortran 90 program that has an array of alpha values with i=1 to 40. I'm trying to output the array into 5 rows of 8 using the code below:
write(4,*) "alpha "
write(4,*)alpha(1), alpha(2), alpha(3), alpha(4), alpha(5), alpha(6), alpha(7), alpha(8)
write(4,*)alpha(9), alpha(10), alpha(11), alpha(12), alpha(13), alpha(14), alpha(15), alpha(16)
write(4,*)alpha(17), alpha(18), alpha(19), alpha(20), alpha(21), alpha(22), alpha(23), alpha(24)
write(4,*)alpha(25), alpha(26), alpha(27), alpha(28), alpha(29), alpha(30), alpha(31), alpha(32)
write(4,*)alpha(33), alpha(34), alpha(35), alpha(36), alpha(37), alpha(38), alpha(39), alpha(40)
where 4 is the desired output file. But when I open the output, there are 10 rows instead of 5 each with 5 values then 3 values alternating. Any idea what I can do to avoid this?
Thanks.
Use formatted IO. List-directed IO (i.e., with "*") is designed to be easy but is not fully specified. Different compilers will produce different output. Try something such as:
write (4, '( 8(2X, ES14.6) )' ) alpha (1:8)
Or use a loop:
do i=1, 33, 8
write (4, '( 8(2X, ES14.6) )' ) alpha (i:i+7)
end do
write (4,"(8(1x,f0.4))") alpha
prints the 40 numbers over 5 lines, because in Fortran "format reversion" the format is re-used when you reach the end of it, with further data printed on a new line.
The site http://www.obliquity.com/computer/fortran/format.html says this about format reversion:
"If there are fewer items in the data transfer list than there are data descriptors, then all of the unused descriptors are simply ignored. However, if there are more items in the data transfer list than there are data descriptors, then forced reversion occurs. In this case, FORTRAN 77 advances to the next record and rescans the format, starting with the right-most left parenthesis, including any repeat-count indicators. It then re-uses this part of the format. If there are no inner parenthesis in the FORMAT statement, then the entire format is reused."
Related
I have had to look up hundreds (if not thousands) of free-text answers on google, making notes in Excel along the way and inserting SAS-code around the answers as a last step.
The output looks like this:
This output contains an unnecessary number of blank spaces, which seems to confuse SAS's search to the point where the observations can't be properly located.
It works if I manually erase superflous spaces, but that will probably take hours. Is there an automated fix for this, either in SAS or in excel?
I tried using the STRIP-function, to no avail:
else if R_res_ort_txt=strip(" arild ") and R_kom_lan=strip(" skåne ") then R_kommun=strip(" Höganäs " );
If you want to generate a string like:
if R_res_ort_txt="arild" and R_kom_lan="skåne" then R_kommun="Höganäs";
from three variables, let's call them A B C, then just use code like:
string=catx(' ','if R_res_ort_txt=',quote(trim(A))
,'and R_kom_lan=',quote(trim(B))
,'then R_kommun=',quote(trim(C)),';') ;
Or if you are just writing that string to a file just use this PUT statement syntax.
put 'if R_res_ort_txt=' A :$quote. 'and R_kom_lan=' B :$quote.
'then R_kommun=' C :$quote. ';' ;
A saner solution would be to continue using the free-text answers as data and perform your matching criteria for transformations with a left join.
proc import out=answers datafile='my-free-text-answers.xlsx';
data have;
attrib R_res_ort_txt R_kom_lan length=$100;
input R_res_ort_txt ...;
datalines4;
... whatever all those transforms will be performed on...
;;;;
proc sql;
create table want as
select
have.* ,
answers.R_kommun_answer as R_kommun
from
have
left join
answers
on
have.R_res_ort_txt = answers.res_ort_answer
& have.R_kom_lan = abswers.kom_lan_answer
;
I solved this by adding quotes in excel using the flash fill function:
https://www.youtube.com/watch?v=nE65QeDoepc
I have a string variable with comma separated numbers that I want to split into four numeric variables.
makeArr
var1a
var1b
var1c
var1d
6,8,13,10
6
8
13
10
10,11,2
10
11
2
7,1,14,3
7
1
14
3
With:
IF (CHAR.INDEX(makeArr,',') >= 1)
f12a=CHAR.SUBSTR(makeArr,1,CHAR.INDEX(makeArr,',')-1).
EXECUTE.
IF (CHAR.INDEX(makeArr,',') >= 1)
f12b=CHAR.SUBSTR(makeArr,CHAR.INDEX(makeArr,',')+1,CHAR.INDEX(makeArr,',')-1).
EXECUTE.
I always get the first variable written without any problems.
This no longer works with the second variable because it has a different length and the comma is also written here.
So I would need a split at the comma and the division of the numbers over the comma.
Since char.substr will only tell you about the location of the first occurence of the search string, you need to start the second search from a new location - AFTER the first occurence, and this gets more and more complicated as you continue. My suggestion is create a copy of your array variable, which you will cut pieces off as you proceed - so that you are only searching for the first occurence of "," every time.
First I recreate your example data to demonstrate on.
data list free/makeArr (a20).
begin data
"6,8,13,10" "10,11,2" "7,1,14,3"
end data.
Now I copy your array into a new variable #tmp. Note that I add a "," at the end so the syntax stays the same for all parts of the array. I add the "#" at the beginning of the name to make it invisible, you can remove it if you want.
It is possible to do the following calculation in steps as you started to do, but nicer to loop throug the steps (especially if this is an example for a longer array).
string f12a f12b f12c f12d #tmp (a20).
compute #tmp=concat(rtrim(makeArr),",").
do repeat nwvr=f12a f12b f12c f12d.
do IF #tmp<>"".
compute nwvr=CHAR.SUBSTR(#tmp,1,CHAR.INDEX(#tmp,',')-1).
compute #tmp=CHAR.SUBSTR(#tmp,CHAR.INDEX(#tmp,',')+1).
end if.
end repeat.
EXECUTE.
Here I found a different solution for what I think is the same problem:
https://www.ibm.com/mysupport/s/question/0D50z00006PsP3tCAF/splitting-a-string-variable-divided-by-commas-into-new-single-variables?language=es
One line of code makes the work:
spssinc trans result=var_1 to var_4 type=20/formula 're.split(", *", makeArr)'.
I have a MATLAB structure with 19 fields. The main field is a 1 x 108033 double with all values numeric. It looks like this, basically 108033 numbers:
pnum: 5384940 5437561 5570271 5661637 5771155 ...
I have another field called inventors which is a 1 x 108033 cell value. Every cell contains a different number of strings. Columns 1 to 5 for example are
inventors: {2x1 cell} {4x1 cell} {1x1 cell} {1x1 cell} {1x1 cell}
For the first column value, the 2 x 1 cell consists of the following values
5012491-01 and 2035147-03 and so on.
I'd like to jointly export these two to a CSV file. The ideal outcome would repeat the number in pnum so that it establishes a clear link between the pnum and the inventors. Thus, the ideal outcome would look something like this (with the contents of what is in the inventors cell displayed).
pnum inventors
5384940 5012491-01
5384940 2035147-03
5437561 5437561-01
5437561 5437561-02
5437561 5437561-03
5437561 5012491-02
5570271 5437561-03
5661637 1885634-08
5771155 5012491-01
I asked a more complex version of this question before but it was not clear enough what the problem was. Hope it is now.
I'm assuming each cell in inventors is a cell array of strings. It wouldn't make sense for these to be actual floating point or intenger numbers, because the dash would subtract the two numbers separating them together. Now, because you're writing to a CSV file, the easiest thing I can think of is to iterate over each number and cell, then repeat the ID number for as many times as there are elements in a cell. First create the right headers, then write your results. Something like this comes to mind:
f = fopen('data.csv', 'w'); %// Open up data for writing
fprintf(f, 'pnum,inventors\n'); %// Write headers
for ii = 1 : numel(pnum) %// For each unique number
inventor = inventors{ii};
for jj = 1 : numel(inventor) %// For each inventor ID
fprintf(f, '%d,%s\n', pnum(ii), inventor{jj}); %// Write the right combo to file
end
end
fclose(f); %// Close the file
fopen here opens up a file called data.csv so we can write things to it. What is returned is a file pointer called f, which we use to write stuff to this file. After, we write the headers of the file, consisting of pnum and inventors. This is a CSV file so there's a comma separating the two. Now, for each unique number, we then access the right slot in inventors then for each unique inventor, add the same unique ID with the right inventor ID as a line in this file. I use fprintf to write things to file using the associated file pointer established earlier. Once we're done, close the file with fclose.
To double check that this works, I've used the small example you've provided in your post:
pnum = [5384940 5437561 5570271 5661637 5771155];
inventors = {{'5012491-01', '2035147-03'}.', {'5437561-01', '5437561-02', '5437561-03', '5012491-02'}.', {'5437561-03'}, {'1885634-08'}, {'5012491-01'}};
Bear in mind that I don't have access to your struct, so you'll have to access the right fields and assign them to the corresponding variables seen above. So if your struct is called something like data, then you'd do this before you run the above code:
pnum = data.pnum;
inventors = data.inventors;
Running the above code I just wrote and opening up the CSV file (which is called data.csv), I get this:
pnum,inventors
5384940,5012491-01
5384940,2035147-03
5437561,5437561-01
5437561,5437561-02
5437561,5437561-03
5437561,5012491-02
5570271,5437561-03
5661637,1885634-08
5771155,5012491-01
I am creating a program which opens an image, and uses the MATLAB ginput command to store x and y coordinates, which are operated on in the loop to fulfill requirements of an if statement and output a number or string corresponding to the region clicked during the ginput session. At the same time, I am using the input command to input a string from the command window relating to these numbers. The ginput session is placed in a while loop so a click in a specific area will end the input session. For each session (while loop), only one or two inputs from the command window are needed. Finally, I am trying to store all the data in a csv or txt file, but I would like it to be tabulated so it is easy to read, i.e. rows and columns with headers. I am including some sample code. My questions are: 1, how can an input of x and y coordinates be translated to a string? It is simple to do this for a number, but I cannot get it to work with a string. 2, any help on printing the strings and number to a tabulated text or cdv file would be appreciated.
Command line input:
prompt='Batter:';
Batter=input(prompt,'s');
While Loop:
count=1;
flag=0;
while(flag==0)
[x,y]= ginput(1);
if (y>539)
flag=1;
end
if x<594 && x>150 && y<539 && y>104
%it's in the square
X=x;
Y=y;
end
if x<524 && x>207 && y<480 && y>163
result='strike'
else
result='ball'
end
[x,y]= ginput(1);
pitch=0;
if x<136 && x>13
%its' pitch column
if y<539
pitch=6;
end
if y<465
pitch=5;
end
if y<390
pitch=4;
end
if y<319
pitch=3;
end
if y<249
pitch=2;
end
if y<175
pitch=1;
end
end
if pitch==0
else
plot(X,Y,'o','MarkerFaceColor',colors(pitch),'MarkerSize',25);
text(X,Y,mat2str(count));
end
count=count+1
M(count,:)=[X,Y,pitch];
end
For the above series of if statements, I would prefer a string output rather than the numbers 1-6 if the condition is satisfied.
The fprintf function is used to print to a file, but I have issues combining the strings and numbers using it:
fileID = fopen('pitches.csv','w');
fid = fopen('gamedata.txt','w');
fmtString = [repmat('%s\t',1,size(Batter,2)-1),'%s\n'];
fprintf(fid,fmtString,Batter,result);
fclose(fid);
for i=1:length(M)
fprintf(fileID,'%6.2f %6.2f %d\n',M(i,1),M(i,2),M(i,3));
end
fclose(fileID);
I have tried adding the string handles to the fprintf command along with the columns of M, but get errors. I either need to store them in an array (How?) and print all the array columns to the file, or use some other method. I also tried a version of the writetable method:
writetable(T,'tabledata2.txt','Delimiter','\t','WriteRowNames',true)
but I can't get everything to work right. Thanks very much for any help.
Let's tackle your questions one at a time:
1, how can an input of x and y coordinates be translated to a string?
You can use the sprintf command in MATLAB. This takes exactly the same syntax as fprintf, but the output of this function will give you a string / character array of whatever you desire.
2, any help on printing the strings and number to a tabulated text or cdv file would be appreciated.
You can still use fprintf but you can specify a matrix as the input. As such, you can do this:
fprintf(fileID,'%6.2f %6.2f %d\n', M.');
This will write the entire matrix to file. However, care must be taken here because MATLAB writes to files in column major format. This means that it will traverse along the rows before going to the next column. If you want to write data row by row, you will need to transpose the matrix first so that when you are traversing down the rows, it will basically do what you want. You will need to keep this in mind before you start trying to write strings to an file. What I would recommend is that you place each string in a cell array, then loop through each element in the cell array and write each string individually line by line.
Hopefully this helps push you in the right direction. Reply back to me in a comment and we can keep talking if you need more help.
I'll begin by saying I am really not good in programming especially in extracting data so please bear with me. I think my problem is simple, I just can't figure out how to do it.
My problem is I want to extract part of the data in a series of excel files stored in the same folder. To be specific, let's say I have 10 excel files with 1000 data in each (from A1:A1000). I want to extract the first 100 data (A1:A100) in each excel files and store it in a single variable with a 10x100 size (each row represents each file).
I would really appreciate if any of you can help me. This would make my data processing a lot faster.
EDIT: I have figured out the code but my next problem is to create another loop such that it will reread again the 10 files but this time extract A101:A200 until A901:A1000.
here's the code i've written:
for k=1:1:10
file=['',int2str(k),'.xlsx'];
data=(xlsread(file,'A1:A100'))';
z(k,:)=data(1,:);
end
I'm not sure how i will edit this part data=(xlsread(file,'A1:A100'))' to do the loop i wanted to do.
my next problem is to create another loop such that it will reread again the 10 files but this time extract A101:A200 until A901:A1000.
Why? Why not extract A1:A1000 in one block and then reshape or otherwise split up the data?
data(k,:)=(xlsread(file,'A1:A1000'))';
Then the A1:A100 data is in data(k,1:100), and so on. If you do this:
data = data(reshape, [10 100 10]);
Then data(:,:,1) should be your A1:A100 values as in your original loop, and so on until data(:,:,10).
This should do it:
for sec = 1:1:10
for k=1:1:10
file=['',int2str(k),'.xlsx'];
section = ['A', num2str(1+(100*(sec-1)), ':A', mum2str(100*sec)]
data=(xlsread(file, section))';
z(k,:)=data(1,:);
end
output(sec) = z;
end
Here's a suggestion to loop through the different cells to read. Obviously, you can change how you arrange the collected data in z. I have done it as the first index representing the different cells to read (1 for 1:100, 2 for 101:200, etc...), the second index being the file number (as per your original code) and the third index the data (100 data points).
% pre-allocate data
z = zeros(10,10,100);
for kk=1:10
cells_to_read = ['A' num2str(kk*100-99) ':A' num2str(kk*100)];
for k=1:10
file=['',int2str(k),'.xlsx'];
data=(xlsread(file,cells_to_read))';
z(kk,k,:)=data(1,:);
end
end