function which has as its input a vector where each element is a positive integer and returns each element of the input vector which is a cube number - r

I'm trying to create a function which has as its input a vector where each element is a positive integer and returns each element of the input vector which is a cube number.
This is my code so far:
positivecube<- function(x){
b<-round(x^(1/3), digits=6)
b%%1==0 &&
b!=1
return(x[b])
}
I'm struggling to remove the 1s from the final vector and to also convert them back to the original cube number. Any help would be great, thank you

You could return the subset of x where the absolute difference between the cube root and the cube root rounded to the nearest integer is very small:
positivecube <- function(x) x[abs(round(x^(1/3)) - x^(1/3)) < 1e-8]
positivecube(1:100)
#> [1] 1 8 27 64

Related

Find position of closest value to another value given a condition in R

let's say I have a vector that increases and then decreases like the simple example below. I want to identify the position (index) in the vector that is closest to a value - but with the condition that the following value must be lower (I always want to pick up the closest value on the downslope of the data).
In the example below, I want the answer to be 13 (rather than 6).
I can't think of a solution using which.min() or match.closest() which would reliably work for this.
Any help gratefully received!
# example vector which increases then decreases
vector <- c(1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1)
# index
index <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
value <- 6.2
Maybe you can use cummax + rev like below
which.min(abs(rev(cummax(rev(vector)))-value))
which gives
[1] 13
Assuming your points always continue to decrease in value after the first decrease, and value is between the point of the first decrease and the last point, you could do this:
closest <- function(value, vec, next_is){
lead_fun <- function(x) c(tail(x, -1), NA)
meets_cond <- get(next_is)(lead_fun(vec), vec)
which.min(abs(vec[meets_cond] - value)) + which.max(meets_cond) - 1
}
closest(6.2, vec = vector, next_is = '<')
# [1] 13
Check which elements in the vector meet your condition, find the index of the closest element in that vector, then add back the number of elements before the first which meets your condition.
Edit: ----------------------------------------
Another version of the function which accepts an arbitrary logical vector which is TRUE for indices meeting a condition:
closest <- function(value, vec, cond_vec){
which.min(abs(vec[cond_vec] - value)) + which.max(cond_vec) - 1
}
Note that this assumes the values matching your condition are all in one contiguous region (not e.g. the first matches, then the third, then the sixth, etc.)
If your condition is that the point comes after the max value:
closest(6.2, vec = vector, cond_vec = seq_along(vector) > which.max(vector))
# [1] 13

Partial String Matching by Row

I'm trying to create a unique column in a data frame that has a numeric of the character matches between two strings from the left side of both strings.
Each row represents has a comparison string, which we want to use as a test against a user given string. Given a dataframe:
df <- data.frame(x=c("yhf", "rnmqjk", "wok"), y=c("yh", "rnmj", "ok"))
x y
1 yhf yh
2 rnmqjk rnmj
3 wok ok
Where x is our comparison string and y is our given string, I'm looking to have the values of "2, 3, 0" output in column z., like so:
x y z
1 yhf yh 2
2 rnmqjk rnmj 3
3 wok ok 0
Essentially, I'm looking to have the given strings (y) checked from left -> right against a comparison string (x), and when the characters don't line up to not check the rest of the string and record the match numbers.
Thank you in advance!
This code works for your example:
df$z <- mapply(function(x, y) which.max(x != y),
strsplit(as.character(df$x), split=""),
strsplit(as.character(df$y), split="")) - 1
df
x y z
1 yhf yh 2
2 rnmqjk rnmj 3
3 wok ok 0
As an outline, strsplit splits a string vector into a list of character vectors. Here, each element of a vector is a single character (with the split="" argument). The which.max function returns the first position where it's argument is the maximum of the vector. Since The vectors returned by x != y are logical, which.max returns the first position where a difference is observed. mapply takes a function and lists and applies the provided function to corresponding elements of the lists.
Note that this produces warnings that the lengths of the strings don't match. This could be addressed in a couple of ways, the easiest is wrapping the function in suppressWarnings if the messages bug you.
As the OP notes int the comments if there are instances where the entire word matches, then which.max returns 1. To return the same length as the string, I'd add a second line of code that combines logical subsetting with the nchar function:
df$z[as.character(df$x) == as.character(df$y)] <-
nchar(as.character(df$x[as.character(df$x) == as.character(df$y)]))

Subsetting a vector with 0s and 1s like seq(3) using [c(0,0,1)]

I tried to subset my vector with [c(0,0,1,0,1...)], but it returned a vector of 1s for each "1" in the binary vector I intended to use as a slicer, not the expected values which were to be picked out of the vector to the left.
seq(3)[as.logical(c(0,0,1))]
Works fine, but
seq(3)[c(0,0,1)]
returns 1, which I didn't expect.
Just trying to understand how or why it's returning 1's instead of pulling the value that coincides with TRUE or 1.
It is treating c(0,0,1) as a vector of position indicies.
Edit: by this I mean it is taking the 0th element twice then the 1st. Nothing in the 0th element so you get a single number which is the first element of your sequence, the number 1.
If you wanted it to be treated as your question suggests you could convert to a logical with as.logical
seq(3)[as.logical(c(0,0,1))]
# [1] 3

Determine the distance of a Vector 3 along another Vector 3

I have 2 3D vectors. (objects with X, Y and Z float values)
In my diagram below, I would like to determine the length of the green line.
This is the distance along Vector 1 that Vector 2 is. Or, the distance from the origin to the end of a line on Vector 1 which is at 90' to Vector 1 and passes thorough the point at the end of Vector 2.
I am doing this in Unity3D so I have access to quite a few helper methods that enable me to get the length of a Vector3 and so on very easily.
The length is obviously
norm(v2)*cos(angle(v1,v2))
and since
cos(angle(v1,v2))=abs(dot(v1,v2))/norm(v1)/norm(v2)
the final formula is
abs(dot(v1,v2))/norm(v1)
One could also say that
e1 = v1/norm(v1)
is the unit vector in the direction of v1, and that the green vector is
dot(e1,v2)*e1
resulting in the same length formula.
This is projection of Vector2 onto Vector1 direction. The simplest way (I think) to find it - using scalar product
D = |V2| * DotProduct(V2, V1) / (|V2| * |V1|) = DotProduct(V2, V1) / |V1|
where |V1| is the length of V1 vector
Im not sure but I think this is what you wanted
Vector3 distance = Vector3.Lerp(Vector3.zero, vector_1, vector_2.sqrMagnitude / vector_1.sqrMagnitude);
http://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html

Finding peaks in vector

I'm trying to find "peaks" in a vector, i.e. elements for which the nearest neighboring elements on both sides that do not have the same value have lower values.
So, e.g. in the vector
c(0,1,1,2,3,3,3,2,3,4,5,6,5,7)
there are peaks at positions 5,6,7,12 and 14
Finding local maxima and minima comes close, but doesn't quite fit.
This should work. The call to diff(sign(diff(x)) == -2 finds peaks by, in essence, testing for a negative second derivative at/around each of the unique values picked out by rle.
x <- c(0,1,1,2,3,3,3,2,3,4,5,6,5,7)
r <- rle(x)
which(rep(x = diff(sign(diff(c(-Inf, r$values, -Inf)))) == -2,
times = r$lengths))
# [1] 5 6 7 12 14
(I padded your vector with -Infs so that both elements 1 and 14 have the possibility of being matched, should the nearest different-valued element have a lower value. You can obviously adjust the end-element matching rule by instead setting one or both of these to Inf.)

Resources