I want to elucidate this behavior in Golang,
Why when you take the memory reference on array and you change values from this reference nothing change in the referencing array.
One example :
var t [5]int
printType(t,"t")
p := &t
printType(p,"p")
x := *p
x[0] = 4
printType(x,"x")
printType(p,"p")
printType(t,"t")
This code return
[t] Type:[5]int Kind:array Adr:%!p([5]int=[0 0 0 0 0]) Value:([0 0 0 0 0])
[p] Type:*[5]int Kind:ptr Adr:0xc4200142d0 Value:(&[0 0 0 0 0])
[x] Type:[5]int Kind:array Adr:%!p([5]int=[4 0 0 0 0]) Value:([4 0 0 0 0])
[p] Type:*[5]int Kind:ptr Adr:0xc4200142d0 Value:(&[0 0 0 0 0])
[t] Type:[5]int Kind:array Adr:%!p([5]int=[0 0 0 0 0]) Value:([0 0 0 0 0])
you can see the memory address is the same but the value "4" is not present.
Method printType
func printType(i interface {},message string) {
k := reflect.TypeOf(i).Kind().String()
fmt.Printf("[%s] Type:%T Kind:%s Adr:%[2]p Value:(%[2]v)\n",message,i,k)
}
Okay found it, the operator ":=" allocate an new memory address.
No, it doesn't allocate anything.
var t [5]int is a value. Note that according to spec [5]int if full type name in this case. You can think of it as of a struct with 5 int fields. Line x := *p makes dereferencing pointer to the t (a value). Assigning value creates a copy of it. If you want to pass a "reference" to t make slice of it: t[:].
Okay found it, the operator ":=" allocates a new memory address.
Related
I basically want to use the function ismember, but for a range. For example, I want to know what data points in array1 are within n distance to array2, for each element in array2.
I have the following:
array1 = [1,2,3,4,5]
array2 = [2,2,3,10,20,40,50]
I want to know what values in array2 are <= 2 away from array1:
indices(1,:) (where array1(1) = 1) = [1 1 1 0 0 0 0]
indices(2,:) (where array1(2) = 2) = [1 1 1 0 0 0 0]
indices(3,:) (where array1(3) = 3) = [1 1 1 0 0 0 0]
indices(4,:) (where array1(4) = 4) = [1 1 1 0 0 0 0]
indices(5,:) (where array1(5) = 5) = [0 0 1 0 0 0 0]
Drawbacks:
My array1 is 496736 elements, my array2 is 9268 elements, so aI would rather not use a loop.
Looping is a valid option here. Intialise an array output to the size of array1 X array2, then loop over all elements in array1 an subtract array2 from that, then check whether the absolute value is less than or equal to 2:
array1 = [1,2,3,4,5];
array2 = [2,2,3,10,20,40,50];
output = zeros(numel(array1), numel(array2),'logical');
for ii = 1:numel(array1)
output(ii,:) = abs(array1(ii)-array2)<=2;
end
output =
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
0 0 1 0 0 0 0
i.e. loops are not the problem.
Thanks to Rahnema1's suggestion, you can initialise output directly as a logical matrix:
output = zeros(numel(array1),numel(array2),'logical');
whose size is just 4.3GB.
On timings: Hans' code runs in a matter of seconds for array1 = 5*rand(496736,1); array2 = 25*rand(9286,1);, the looped solution takes about 15 times longer. Both solutions are equal to one another. obcahrdon's ismembertol solution is somewhere in between on my machine.
On RAM usage:
Both implicit expansion, as per Hans' answer, as well as the loop suggested in mine work with just 4.3GB RAM on your expanded problem size (496736*9286)
pdist2 as per Luis' answer and bsxfun as per Hans' on the other hand try to create an intermediate double matrix of 34GB (which doesn't even fit in my RAM, so I cannot compare timings).
obchardon's ismembertol solution outputs a different form of the solution, and takes ~5.04GB (highly dependent on the amount of matches found, the more, the larger this number will be).
In general this leads me to the conclusion that implicit expansion should be your option of choice, but if you have R2016a or earlier, ismembertol or a loop is the way to go.
Using implicit expansion, introduced in MATLAB R2016b, you can simply write:
abs(array1.' - array2) <= 2
ans =
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
0 0 1 0 0 0 0
For earlier MATLAB versions, you can get this using the bsxfun function:
abs(bsxfun(#minus, array1.', array2)) <= 2
ans =
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
0 0 1 0 0 0 0
Hope that helps!
P.S. On the "MATLAB is slow for loops" myth, please have a look at that blog post for example.
EDIT: Please read Adriaan's answer on the RAM consumption using this and/or his approach!
If you have the Statistics Toolbox, you can use pdist2 to compute the distance matrix:
result = pdist2(array1(:), array2(:)) <= 2;
As noted by #Adriaan, this is not efficient for large input sizes. In that case a better approach is a loop with preallocation of the logical matrix output, as in his answer.
You can also use ismembertol with some specific option:
A = [1,2,3,4,5];
B = [2,2,3,10,20,40,5000];
tol = 2;
[~,ind] = ismembertol([A-tol;A+tol].',[B-tol;B+tol].',tol, 'ByRows', true, ...
'OutputAllIndices', true, 'DataScale', [1,Inf])
It will create a 5x1 cell array containing the corresponding linear indice
ind{1} = [1,2,3]
ind{2} = [1,2,3]
...
ind{5} = [3]
In this case using linear indices instead of logical indices will greatly reduce the memory consumption.
I have arranged a large number of arrays into a list and I have a vector which is the same length as the number of arrays with different values. For each array in the list, I would like to input the successive specific values in the vector into the same position in the successive arrays in the list.
For example, if I had 10 arrays of 5x3x10 in a list, and a vector of length 10 with 10 different values, I would like the first value of the vector to go into the first array at position [1,1,1], the second value of the vector to go into the second array at position [1,1,1], the third value of the vector to go into the third array at position [1,1,1], and so on to the tenth value of the vector going into the tenth array at position [1,1,1].
Here is my current code (simplified).
All the variables/arrays are provide as necessary.
Currently I have a function that attempts to do this, but the way its written does not allow for the successive values of the variable to be put into the successive arrays. Rather the function tries to put all the values of the variable into the position [1,1,1] of each array, and as such, returns an error.
#Starting variables
dt = 1
person_id <- c("a", "b", "c", "d", "e")
clinic_id <- c("c1", "c2", "c3")
time_id <- seq(2008.5, 2017.5, by = dt)
first <- c(13,14,10,8,6,8,7,9,10,12)
second <- c(16,8,9,4,5,6,2,3,4,5)
numbers <- data.frame(first,second)
dims <- list(person = person_id,
clinic = clinic_id,
time = time_id)
#Create 10 arrays
for (i in 1:10) {
assign(paste("modarrays", i, sep=""),
array(NA, lengths(dims), dims) )
}
#Creating array list with 10 arrays
modarraysall <- lapply(ls(pattern="modarrays"),get)
arraynames <- sapply(ls(pattern="modarrays"),as.name)
names(modarraysall) <- arraynames
#Initial values in array
initval <- function(x){
x[,,1] <- 0.0
x <- x
}
modarraysallnew <- lapply(modarraysall, initval)
#Values from vector of dataframe into array
#This is where it all goes wrong.
numbersintoarray <- function(x){
x[1,1,1] <- numbers$first
x <- x
}
modarraysallnew <- lapply(modarraysallnew, numbersintoarray)
There is no output from this function implementation because I get an error saying
Error in x[1, 1, 1] <- numbers$first :
number of items to replace is not a multiple of replacement length
I think I know what is wrong. This function wants to put the value of numbers$first into position [1,1,1] of each array across the list. However, numbers$first is a length of 10 values where as position [1,1,1] in each array is only one position. Therefore, I know this function is wrong. But how do I write a function that takes each successive value from numbers$first and puts that into each successive array in the list at position [1,1,1].
Below I have shown what I would like the arrays too look like afterwards.
modarrays1[,,1]
clinic
person c1 c2 c3
a 13 0 0
b 0 0 0
c 0 0 0
d 0 0 0
e 0 0 0
modarrays1[,,2]
clinic
person c1 c2 c3
a 14 0 0
b 0 0 0
c 0 0 0
d 0 0 0
e 0 0 0
modarrays1[,,3]
clinic
person c1 c2 c3
a 10 0 0
b 0 0 0
c 0 0 0
d 0 0 0
e 0 0 0
....
modarrays10[,,1]
clinic
person c1 c2 c3
a 12 0 0
b 0 0 0
c 0 0 0
d 0 0 0
e 0 0 0
I realize I could write this out one array at a time. However, in my actual model code I have 54 arrays in the list so would like to be able to write a function to do this instead.
If you want to perform a function element-wise across two different lists or vectors, your best bet is to use mapply or Map. They need a function that takes as many arguments as lists/vectors you are providing. So in your case, you could try:
numbersintoarray <- function(arr, val) {
arr[1, 1, 1] <- val
return(arr)
}
m <- Map(numbersintoarray, modarraysallnew, numbers$first)
m$modarrays1[ , , 1]
# clinic
# person c1 c2 c3
# a 13 0 0
# b 0 0 0
# c 0 0 0
# d 0 0 0
# e 0 0 0
I am trying to write a svm code, but i am literally a beginner in matlab.
So in my code, in a for loop, i should store predictions. The data is like this:
testIdx = [1 1 1 0 0 0 0 0 1 0 1 1]'; % i wrote it like this but it says logical
and
pred = [1 1 1 0 1 0]'; % again logical
So i want to form a 12 length array and turn its 1st,2nd,3rd,9th,11th,12th elements into 1 1 1 0 1 0, and likewise rest of test elements into another set of 0/1s in other iteration.
If possible let it be a normal array, not logical. Thanks in advance
I did it myself old style but there must be a shorter direct way right?
Y = zeros ( size(testIdx,1), 1) ;
a=1;
for i = 1:size(testIdx,1)
if testIdx(i) ==1
Y(i) = pred(a);
a=a+1;
end
end
If you create testIdx and pred the way you specified, then they are double and not logical type. To use logical indexing, it is easiest if testIdx is converted to the logical type. Then you can simply use
testIdx = [1 1 1 0 0 0 0 0 1 0 1 1]';
pred = [1 1 1 0 1 0]';
Y = zeros(size(testIdx));
Y(logical(testIdx)) = pred;
With Y(logical(testIdx), you select all indexes which are set to 1 in the testIdx vector and then write predto these indexes.
Say, I have Index array I = [2 4 6]
Another, array A =[1 0 0]
I want to insert elements of array A in array C at position 2 , 4 and 6.
Array C is initially empty.
Run 2: I = [1, 7, 8]
A = [0 0 1]
I would want to insert elements of array A in array C at position 1 , 7 and 8.
And, so on.
Please help.
Thanks.
Cheery essentially answered the question for you, but in order to be complete, simply use the array I and index into C and use I to place the values of A into the corresponding slots in C. As such:
C(I) = A;
If C was not already allocated, then C will pad whatever you didn't index with zeroes. As such, given your two examples, this is what we get:
I1 = [2 4 6];
I2 = [1 7 8];
A1 = [1 0 0];
A2 = [0 0 1];
C1(I1) = A1
C2(I2) = A2
C1 =
0 1 0 0 0 0
C2 =
0 0 0 0 0 0 0 1
However, because your array A already has zeroes, you can't really see the effect of this type of assignment. If you change up your array A into some other values that don't include zero, then you'll see that this does work.
I recently picked up the Go language, and now I am confused with the following code:
package main
import "fmt"
func main() {
a := make([]int, 5)
printSlice("a", a)
b := make([]int, 0, 5)
printSlice("b", b)
c := b[:2]
printSlice("c", c)
d := c[2:5]
printSlice("d", d)
}
func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d %v\n",
s, len(x), cap(x), x)
}
And the result:
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0] //why the capacity of c not 2 but 5 instead
d len=3 cap=3 [0 0 0]
c is a slice taken from the array b. This isn't a copy, but just a window over the 2 first elements of b.
As b has a capacity of 5, c could be extended to take the 3 other places (in fact it makes a new slice but over the same place in memory).
The maximal capacity of the slice is the capacity of the underlying array minus the position of the start of the slice in the array :
array : [0 0 0 0 0 0 0 0 0 0 0 0]
array : <---- capacity --->
slice : [0 0 0 0]
slice : <---- capacity --->
Maybe this program will make it more clear that c and d are just windows over b :
func main() {
b := make([]int, 0, 5)
c := b[:2]
d := c[1:5] // this is equivalent to d := b[1:5]
d[0] = 1
printSlice("c", c)
printSlice("d", d)
}
Output :
c len=2 cap=5 [0 1] // modifying d has modified c
d len=4 cap=4 [1 0 0 0]
Note that in go 1.2 (Q4 2013, 1.2rc1 is available now), you can associate to a slice a capacity of its own (instead of a capacity deduced from the underlying array).
See "Three-index slices", and the design document.
A slicing operation creates a new slice by describing a contiguous section of an already-created array or slice:
var array [10]int
slice := array[2:4]
The capacity of the slice is the maximum number of elements that the slice may hold, even after reslicing; it reflects the size of the underlying array.
In this example, the capacity of the slice variable is 8.
(capacity of the underlying array minus the position of the start of the slice in the array)
array : [0 0 0 0 0 0 0 0 0 0]
array : <---- capacity --->
slice : [0 0]
slice : <-- capacity --> 8 (10-2)
Go 1.2 adds new syntax to allow a slicing operation to specify the capacity as well as the length.
A second colon introduces the capacity value, which must be less than or equal to the capacity of the source slice or array, adjusted for the origin.
For instance,
slice = array[2:4:6]
array : [0 0 0 0 0 0 0 0 0 0]
array : <---- capacity ---> 10
slice : [0 0]
slice : <- cap-> 4 (6-2)
sets the slice to have the same length as in the earlier example but its capacity is now only 4 elements (6-2).
It is impossible to use this new slice value to access the last two elements of the original array.
The main argument is to give programmers more control over append.
a[i : j : k]
That slice has:
indices starting at 0
length equals to j - i
capacity equals to k - i
The evaluation panics if i <= j <= k <= cap(a) is not true.