Create a for loop that checks whether a numeric vector has at least two zeros in
a row. If so, it prints the position (index) of the first zero.
Here is a version by using rle + inverse.rle
findConZeros <- function(x) {
u <- rle(unlist(strsplit(as.character(x),""))==0)
u$values <- with(u,lengths>=2&values)
which(inverse.rle(u))
}
such that
> findConZeros(1200011)
[1] 3 4 5
> findConZeros(40400)
[1] 4 5
Below is a for loop version
findConZeros_forloop <- function(x) {
s <- unlist(strsplit(as.character(x),""))
res <- c()
for (i in seq_along(s)) {
if (all(s[i:(i+1)]=="0") & i < length(s)) res <- c(res,i,i+1)
}
unique(res)
}
which gives
> findConZeros_forloop(1200011)
[1] 3 4 5
> findConZeros_forloop(40400)
[1] 4 5
Related
I want to prevent running the i=j case and substitute it as NA in R. Here I prepared a small example. When i=j, I have the output 0. But I want to print it as NA. How can I do this one? Thanks.
n = 5
for(j in 1:(n-1)){
for(i in 0:(n-2)){
print(2^(abs(i-j)))
}
}
The outputs are 2, 1, 2, 4,....
Either if (i==j) { print(NA) } else { ... } or if (i==j) {print(NA); break}
Why don't you use if statement?
n = 5
for(j in 1:(n-1)){
for(i in 0:(n-2)){
if(i == j){
print(NA)
} else{
print(2^(abs(i-j)))
}
}
}
Just for fun here is a vectorized version that might be much more efficient, depending on the size of n. It returns a vector, which you could print line by line if that is your desired output.
The idea is to generate the pairings from the nested loop using expand.grid, then subtracting these vectors from each other and setting the cases where i==j (i.e. the difference being 0) to NA.
2^abs({
rd <- do.call(`-`, asplit(expand.grid(j=0:(n-2), i=1:(n-1)), 2))
rd[rd==0] <- NA; rd})
You can try ifelse or if ... else .... Below is one option with ifelse:
n <- 5
for (j in 1:(n - 1)) {
for (i in 0:(n - 2)) {
print(ifelse(i == j, NA, 2^(abs(i - j))))
}
}
giving
[1] 2
[1] NA
[1] 2
[1] 4
[1] 4
[1] 2
[1] NA
[1] 2
[1] 8
[1] 4
[1] 2
[1] NA
[1] 16
[1] 8
[1] 4
[1] 2
Another option is using NA^(i==j) as a mask, e.g.,
n <- 5
for (j in 1:(n - 1)) {
for (i in 0:(n - 2)) {
print(2^(abs(i - j)) * NA^(i == j))
}
}
Find the number of entries in each row which are greater than 4.
set.seed(75)
aMat <- matrix( sample(10, size=60, replace=T), nr=6)
rowmax=function(a)
{
x=nrow(a)
y=ncol(a)
i=1
j=1
z=0
while (i<=x) {
for(j in 1:y) {
if(!is.na(a[i][j])){
if(a[i][j]>4){
z=z+1
}
}
j=j+1
}
print(z)
i=i+1
}
}
rowmax(aMat)
It is showing the error. I don't want to apply in built function
You could do this easier counting the x that are greater than 4 using length.
rowmax2 <- function(x) apply(x, 1, function(x) {x <- na.omit(x);length(x[x > 4])})
rowmax2(aMat)
# [1] 8 7 8 7 4 3
If you wanted to do this absolutely without any shortcut you could use two for loops. 1 for each row and another for each value in the row.
rowmax = function(a) {
y=nrow(a)
result <- numeric(y)
for(j in seq_len(y)) {
count = 0
for(val in a[j, ]) {
if(!is.na(val) && val > 4)
count = count + 1
}
result[j] <- count
}
return(result)
}
rowmax(aMat)
#[1] 8 7 8 7 4 3
If you wanted to do this using in-built functions in base R you could use rowSums.
rowSums(aMat > 4, na.rm = TRUE)
#[1] 8 7 8 7 4 3
There are several errors in you code:
You should put z <- 0 inside while loop
You should use a[i,j] for the matrix indexing, rather than a[i][j]
Below is a version after fixing the problems
rowmax <- function(a) {
x <- nrow(a)
y <- ncol(a)
i <- 1
j <- 1
while (i <= x) {
z <- 0
for (j in 1:y) {
if (!is.na(a[i, j])) {
if (a[i, j] > 4) {
z <- z + 1
}
}
j <- j + 1
}
print(z)
i <- i + 1
}
}
and then we get
> rowmax(aMat)
[1] 8
[1] 7
[1] 8
[1] 7
[1] 4
[1] 3
A concise approach to make it is using rowSums, e.g.,
rowSums(aMat, na.rm = TRUE)
i have an assignment for studies and i need to create a function that takes a vector as input and creates another vector, which, at every position has a cumulative sum of the previous ones and itself, it might be unclear but i have some code, and have no idea whats wrong. I cant use cumsum()
SumaKumul <- function(x)
{
result <- c()
for(i in x)
{
result[i] <- sum(x[1:i])
}
return(result)
}
SumaKumul(c(2,3,4,5))
and thats what i get
> SumaKumul(c(2,3,4,5))
[1] NA 5 9 14 NA
>
You should use seq_along(x), rather than x in your for loop
SumaKumul <- function(x)
{
result <- c()
for(i in seq_along(x))
{
result[i] <- sum(x[1:i])
}
return(result)
}
such that
> SumaKumul(c(2,3,4,5))
[1] 2 5 9 14
You can add 1:length(x) in your for loop of a function to iterate over a vector:
SumaKumul <- function(x)
{
result <- c()
for(i in 1:length(x))
{
result[i] <- sum(x[1:i])
}
return(result)
}
SumaKumul(c(2,3,4,5))
# [1] 2 5 9 14
I want to have the indices for every "1" on a row of a matrix. However, when I coded as the followings, only the result for the last row outputs. How can I fix the problem and what is wrong with my code?
adjacency <- function(x) {
num_row <- nrow(x)
for (i in num_row){
output <- which (x[i,]==1)
print(output)
}
result <- list (output)
print(result)
}
A <- matrix(c(NA,1,0,1,1,NA,1,0,0,1,NA,1,1,0,1,NA),nrow=4)
A
adjacency(A)
You were only iterating over a single value, the number of rows in your matrix, and not over each row:
adjacency <- function(x) {
num_row <- nrow(x)
result<-list()
for (i in 1:num_row){
result[[i]] <- which (x[i,]==1)
}
print(result)
}
A <- matrix(c(NA,1,0,1,1,NA,1,0,0,1,NA,1,1,0,1,NA),nrow=4)
A
adjacency(A)
[[1]]
[1] 2 4
[[2]]
[1] 1 3
[[3]]
[1] 2 4
[[4]]
[1] 1 3
I write the following code in r
Candidate <- vector(mode="list", length=3)
names(Candidate)<-c("Survivex","Survivey","Splitx")
Candidate[]<-0
for(i in 1:10)
{
if(i%%2==0)
Candidate["Survivex"]<-i
else if(i%%5==0)
Candidate["Survivey"]<-i
else
Candidate["Splitx"]<-i
}
which gives the following result
Candidate
$Survivex
[1] 10
$Survivey
[1] 5
$Splitx
[1] 9
but my desired result is like
Candidate
$Survivex
[1] 2 4 6 8 10
$Survivey
[1] 5 10
$Splitx
[1] 1 3 7 9
how can I modify my codes to get the required result
Concatenate the new results to the existing ones instead of replacing them, and
use double bracket extraction instead of single bracket subsetting. For example,
Candidate <- vector(mode="list", length=3)
names(Candidate) <- c("Survivex", "Survivey", "Splitx")
for(i in 1:10)
{
if(i %% 2 == 0)
Candidate[["Survivex"]] <- c(Candidate[["Survivex"]], i)
else if(i %% 5 == 0)
Candidate[["Survivey"]] <- c(Candidate[["Survivey"]], i)
else
Candidate[["Splitx"]] <- c(Candidate[["Splitx"]], i)
}
You could work with lapply() and functions to get what you want.
Candidate <- lapply(1:3, function(j) unlist(do.call(cbind, lapply(1:10, function(i) {
if (i %% 2 == 0) Candidate[[1]] <- i
else if (i %% 5 == 0) Candidate[[2]] <- i
else Candidate[[3]] <- i
if (i %% 5 == 0) Candidate[[2]] <- i
return(Candidate)
}))[j, ]))
names(Candidate) <- nms
Result
> Candidate
$`Survivex`
[1] 2 4 6 8 10
$Survivey
[1] 5 10
$Splitx
[1] 1 3 7 9
Data
Candidate <- vector(mode="list", length=3)
nms <- names(Candidate) <- c("Survivex", "Survivey", "Splitx")