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
Related
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)
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
I'm trying to convert a while loop to a recursion.
I know the while loop is more efficient, but I'm trying to understand how to convert a for/while loop to recursion, and recursion to a for/while/if loop.
my function as I'm using a while loop:
harmon_sum <- function(x){
n <- 1
sum <- 0
while (sum < x)
{
sum <- sum + (1/n)
n <- (n +1)
}
return(n)
}
This function takes some numeric value, suppose x=2, and returns the number of objects for the harmonic sum that you need to sum up in order to create a greater number then x. (for x=2, you'd need to sum up the first 5 objects of the harmonic sum)
[![harmonic sum][1]][1]
**example**: `harmon_sum <- function(x){
n <- 1
sum <- 0
while (sum < x)
{
sum <- sum + (1/n)
print(sum)
n <- (n +1)
print(n)
}
return(n)
}
> harmon_sum(x =2)
[1] 1
[1] 2
[1] 1.5
[1] 3
[1] 1.833333
[1] 4
[1] 2.083333
[1] 5
[1] 5`
my version for the recursive function:
harmon_sum2 <- function(x, n =1){
if( x<= 0){
return(n-1)
}
else {
x <- (x- (1/(n)))
harmon_sum2(x, n+1)
}
}
which returns me the wrong answer.
I'd rather find a solution with just one variable (x), instead of using two variables (x, n), but I couldn't figure a way to do that.
It seems to me that if you change return(n-1) to return(n) you do get the right results.
harmon_sum2 <- function(x, n=1){
if( x <= 0){
return(n)
}
else {
x <- (x- (1/(n)))
harmon_sum2(x, n+1)
}
}
harmon_sum(2)
[1] 5
harmon_sum2(2)
[1] 5
harmon_sum(4)
[1] 32
harmon_sum2(4)
[1] 32
Your function needs to know n. If you don't want to pass it, you need to store it somewhere where all functions on the call stack can access it. For your specific case you can use sys.nframe instead:
harmon_sum2 <- function(x){
if( x<= 0){
return(sys.nframe())
}
else {
x <- (x- (1/(sys.nframe())))
harmon_sum2(x)
}
}
harmon_sum(8)
#[1] 1675
harmon_sum2(8)
#[1] 1675
However, this doesn't work if you call your function from within another function:
print(harmon_sum2(8))
#[1] 4551
Another alternative is the approach I demonstrate in this answer.
I have written a function to store the diagonal elements of a matrix into a vector. but the output is not as I expected. The code is:
diagonal <- function(x) {
for (i in nrow(x)) {
for (j in ncol(x)) {
if (i == j) {
a <- x[i, j]
}
}
}
print(a)
}
I am passing a matrix to the function.
What is wrong with the code?
We can use the diag function
diag(m1)
#[1] 1 5 9
Or
m1[col(m1)==row(m1)]
#[1] 1 5 9
If we are using the for loop, we are looping by the sequence of rows and columns i.e 1:nrow(x)/1:ncol(x) and not by nrow(x)/ncol(x).
diagonal <- function(x) {
a <- numeric(0)
for( i in 1:nrow(x)){
for(j in 1:ncol(x)){
if(i == j) {
a <- c(a, x[i,j])
}
}
}
a
}
diagonal(m1)
#[1] 1 5 9
data
m1 <- matrix(1:9, ncol=3)
x <- c(1,2,3,2,1)
table(x)
# x
# 1 2 3
# 2 2 1
Outputs how many times each element occur in the vector.
I am trying to imitate the above function using function()
Below is my code:
TotalTimes = function(x){
times = 0
y = unique(x)
for (i in 1:length(y)) {
for (i in 1:length(x)) {
if(y[i] == x[i])
times = times + 1
}
return(times)
}
}
What would be the right approach?
Here's a one-liner, using rle():
f <- function(x) {
with(rle(sort(x)), setNames(lengths, values))
}
f(c(1,2,3,2,1))
# 1 2 3
# 2 2 1
Alternatively, here's an option that's less "tricky", and is probably a better model for learning to code in an R-ish way:
f2 <- function(x) {
ss <- sort(x)
uu <- unique(ss)
names(uu) <- uu
sapply(uu, function(u) sum(ss == u))
}
f2(c(1,2,3,2,1))
# 1 2 3
# 2 2 1
function(x) {
q = sapply(unique(x), function(i) sum(x == i))
names(q) = unique(x)
return(q)
}
Here is one method using base R:
# data
x <- c(1,2,3,2,1)
# set up
y <- sort(unique(x))
counts <- rep_len(0, length.out=length(y))
names(counts) <- y
for(i in seq_along(x)) {
counts[x[i] == y] <- counts[x[i] == y] + 1
}
Wrapping it in a function:
table2 <- function(x) {
# transform x into character vector to reduce search cost in loop
x <- as.character(x)
y <- sort(unique(x))
counts <- rep_len(0, length.out=length(y))
names(counts) <- y
for(i in seq_along(x)) {
counts[x[i]] <- counts[x[i]] + 1L
}
return(counts)
}
This version only accepts a single vector, of course. At #Frank's suggestion, the function version is slightly different, and possibly faster, in that it transforms the input x into a character. The potential speed up is in the search in counts[x[i]] where the name in counts is referred to (as x[i]), rather than performing a search using "==."