I have two sets x [xmin,xmax] and y [ymin, ymax] and I would like to execute a function going stepwise from the min to the max values of x and y. So I want to apply a function to the Cartesian product of x and y. I would then like to save each combination as a row to a CSV file. I've been trying for some time with a do loop, but got a bit stuck on how to create the list in the end. For instance:
for x: 1 thru 2 step 1 do
for y: 1 thru 2 step 1 do
print([x,y,find_root (exp(a*x) = y, a, 0, 1)])
I'd get the values of x and y and the function of all combinations, but I struggle to save it and export it to a CSV, because I don't know how to create the list with [[1,1,function(1,1)],[1,2,function(1,2)],[2,1,function(2,1)],[2,2,function(2,2)]], that I could export with write_data.
Alternatively, I'd like to use:
xlist:makelist(x,x,1,2,1);
ylist:makelist(y,y,1,2,1);
create_list([x,y,x^y],x,xlist,y,ylist);
In this case I don't know how to include the function in create list or how to use map.
How do I do the above or is there a better way?
About speeding up the construction of the 1 million item list, how about solving the equation just once and then substituting values of x and y? E.g.:
solve (exp(a*x) = y, a);
my_solution : rhs (first (%));
create_list ([x, y, ev (my_solution)], x, xlist, y, ylist);
Here ev evaluates my_solution with the current values of the variables it contains (namely x and y).
About writing a CSV file, try this:
write_data (my_list, "my_output_file", 'comma);
Related
I have a table with values extracted from a csv I want to make a contour plot from.
Let's use this table as an example
tdata.x = [1;2;1;2];
tdata.y = [3;3;4;4];
tdata.z = randn(4,1);
tdata=struct2table(tdata);
>> tdata
tdata =
4×3 table
x y z
_ _ _______
1 3 0.53767
2 3 1.8339
1 4 -2.2588
2 4 0.86217
I would like to pivot this such that I can use it for plotting a contour, so in principle I want a 2x2 z matrix where rows/columns are given by y and x respectively, something in this direction:
x 1 2
y
3 0.53767 1.8339
4 -2.2588 0.86217
where the first row are the x coordinates, the first columns is the y coordinates and in-between are the corresponding z-values. So that is to say the z-value corresponding to (x,y)=(1,4) is -2.2588.
Note, I am going to use this grid for other things down the road so solutions involving interpolation are not valid, as well the data is guaranteed to be given on a grid.
You can use unstack, i.e.
t = unstack( tdata, {'z'}, {'x'} );
Which will give you this:
Note that the column names are all prefixed with x because you can't have a column name beginning with a number. You should be able to extract the x values back again, especially if they're always integers it won't be too hard, for whatever operations you want from here...
Here's the approach I would use:
result = full(sparse(findgroups(tdata.y), findgroups(tdata.x), tdata.z));
Equivalently, you could use the third output of unique instead of findgroups, or accumarray instead of sparse:
[~, ~, ux] = unique(tdata.x);
[~, ~, uy] = unique(tdata.y);
result = accumarray([uy ux], tdata.z);
I am trying to extract the coordinates located in the variable x within a .mat structure. I would like to print them as a three column matrix. Let's say:
-5543837.67700032 -2054567.16633347 2387852.25825667
4641938.565315761 393003.28157792 4133325.70392322
-3957408.7414133 3310229.46968631 3737494.72491701
1492206.38965564 -4458130.51073730 4296015.51539152
4075539.69798060 931735.497964395 4801629.46009471
3451207.69353006 3060375.44622100 4391915.05780934
I know that I can get them with
file=load('./filee_scan.mat')
stat = [file.scan.stat]';
x = [stat.x]';
But I get something like:
-5543837.67700032
-2054567.16633347
2387852.25825667
4641938.565315761
393003.28157792
4133325.70392322
% :: and so on
I would like to print them as I showed at the beginning (x as a vector of 3 coordinates and one line per station) but I don't know how to treat them. I have tried with loops but I really don't know how to express them.
How can I display my coordinates as an n -by- 3 matrix?
This is the scan file:
This is x:
[stat.x].' gives you a flattened vector, as you've seen. You can reshape() that vector to the desired format:
x = reshape(x,3,[]).';
This reshapes first to 3 rows and n columns (your number of stations), then transposed to have n rows of 3 columns.
For a short introduction on how reshape works, see this answer of mine.
I'm trying to create a list of 50 random numbers let's say between 100 and 500 with one formula in Gsheets. Is there any formula like 'apply this to x cells'?
What I tried so far is (and doesn't work). I hoped randarray function will 'force' randbetween function to create 2D array (randarray creates a list of numbers between 0 and 1).
={
RANDARRAY(50,1), ARRAY_CONSTRAIN(RANDBETWEEN(100,500),50,1)
}
Error
Function ARRAY_ROW parameter 2 has mismatched row size. Expected: 50. Actual: 1.
So this error indicates that array_constrain didn't help either.
try like this:
=ARRAYFORMULA(RANDBETWEEN(ROW(A100:A149), 500))
In generic terms, if you need N random numbers, between X and Y, you would combine the following formulas:
RandBetween(X, Y)
Row(cell_ref)
Indirect(string_cell_ref)
ArrayFormula(array_formula)
Details
When combining a Row(cell_ref) with an ArrayFormula, you can specify a cell range or simply a number range:
ArrayFormula(Row(1:50))
The above example generates a one dimensional array (column) with the numbers 1 through 50. In order to programmatically change the number, we use the Indirect function to specify the upper bound of the range, N:
ArrayFormula(Row(Indirect("1:"&N)))
N can be a named range, hard coded, or a cell reference containing a number greater than 0. Because you want each row to contain a random number between X and Y, you need to eliminate the sequential number in each array position by multiplying the number generated by the above formula by zero:
ArrayFormula(Row(Indirect("1:"&N))*0)
which generates a on dimensional array (column) of N zeros. Now you can combine this as follows to generate a one dimensional array (column) of N random numbers between X and Y:
Solution
ArrayFormula(RandBetween(Row(Indirect("1:"&N))*0+X, Y))
You could use named ranges for N, X, and Y; hard code them eg. 50, 100, 500; or use simple cell references as in the example below:
ArrayFormula(RandBetween(row(indirect("1:"&B1))*0+B2, B3))
GSheet Example
I am writing this in IDL.
I want to pass a list of numbers in array x that goes through function y, where then all y values go into an array z, that will be plotted x vs. z.
I have tried to solve this numerous ways. Initially, I was using lists, where it is easy to use the 'list.add' function to add new elements to an array. However, I can only plot arrays in IDL, and not list (thus getting an error). I have been messing around with the code for quite some time, so hopefully I can get some pointers in the right direction
z = [] ; array to hold y data
x = [1,2,3,4] ; x data
FOREACH element, x DO BEGIN
y = x+3
z.add,y
ENDOFREACH
; the plot
p = SCATTERPLOT(x,z)
I am hoping to get a simple scatter plot from this, but I do not know how to change my arrays.
There are two main ways to do this:
Concatenate arrays. For example, y = [y, 3] tacks on a 3 at the end of the y array. This is slow if you intend to this "a lot".
Use a list for building the list of values, then use the toArray() method at the end to get and array which can be plotted.
I have a large data set with two arrays, say x and y. The arrays have over 1 million data points in size. Is there a simple way to do a scatter plot of only 2000 of these points but have it be representative of the entire set?
I'm thinking along the lines of creating another array r ; r = max(x)*rand(2000,1) to get a random sample of the x array. Is there a way to then find where a value in r is equal to, or close to a value in x ? They wouldn't have to be in the same indexed location but just throughout the whole matrix. We could then plot the y values associated with those found x values against r
I'm just not sure how to code this. Is there a better way than doing this?
I'm not sure how representative this procedure will be of your data, because it depends on what your data looks like, but you can certainly code up something like that. The easiest way to find the closest value is to take the min of the abs of the difference between your test vector and your desired value.
r = max(x)*rand(2000,1);
for i = 1:length(r)
[~,z(i)] = min(abs(x-r(i)));
end
plot(x(z),y(z),'.')
Note that the [~,z(i)] in the min line means we want to store the index of the minimum value in vector z.
You might also try something like a moving average, see this video: http://blogs.mathworks.com/videos/2012/04/17/using-convolution-to-smooth-data-with-a-moving-average-in-matlab/
Or you can plot every n points, something like (I haven't tested this, so no guarantees):
n = 1000;
plot(x(1:n:end),y(1:n:end))
Or, if you know the number of points you want (again, untested):
npoints = 2000;
interval = round(length(x)/npoints);
plot(x(1:interval:end),y(1:interval:end))
Perhaps the easiest way is to use round function and convert things to integers, then they can be compared. For example, if you want to find points that are within 0.1 of the values of r, multiply the values by 10 first, then round:
r = max(x) * round(2000,1);
rr = round(r / 0.1);
xx = round(x / 0.1);
inRR = ismember(xx, rr)
plot(x(inRR), y(inRR));
By dividing by 0.1, any values that have the same integer value are within 0.1 of each other.
ismember returns a 1 for each value of xx if that value is in rr, otherwise a 0. These can be used to select entries to plot.