How to Reduce Values in a List in R - r

New R learner here. I have a list of odd numbers that I produced in R. I have 1. . .23 odd. "Three" is supposed to be spelled out. I only need the rows with the values of 1-11 odd not 13-23 odd. I am unable to reduce the list to be 1-11. How can I get rid of the values that are not needed?
for (i in 0:11)
{
i<-(i*2+1)
{
if (i <= 11)
{
if (i == 3) ("three")
}
}
print(i)
}
[1] 1
[1] 3
[1] 5
[1] 7
[1] 9
[1] 11
[1] 13
[1] 15
[1] 17
[1] 19
[1] 21
[1] 23

Re-arranging and tweaking your code
for (i in 0:11){
i <- (i*2+1)
if(i==3){
print("Three")
next
}
if(i<=11){
print(i)
}
}
#Output
# [1] 1
# [1] "Three"
# [1] 5
# [1] 7
# [1] 9
# [1] 11

Base R one liner:
ifelse(c(1:11)[1:11 %% 2 > 0] == 3, "three", c(1:11)[1:11 %% 2 > 0])
Maintaining flow control in loop (as requested):
x <- vector("character", sum(0:11 %% 2 >0))
seq_vals <- 1:11
odd_vals <- seq_vals[1:11 %% 2 > 0]
for(i in odd_vals){
if(i != 3){
x <- c(x, as.character(i))
}else{
x <- c(x, "three")
}
}
x[x != ""]

Related

Sum even numbers without using while

I am stuck with a sum that I don't know how to solve this problem. I need to sum even numbers from 2 to 20, and this numbers sum 3.
n<-20
j<-0
for (i in 1:n) {
if(i %% 2 == 0)
j<-i+3
print(j)
}
Output:
[1] 0
[1] 5
[1] 5
[1] 7
[1] 7
[1] 9
[1] 9
[1] 11
[1] 11
[1] 13
[1] 13
[1] 15
[1] 15
[1] 17
[1] 17
[1] 19
[1] 19
[1] 21
[1] 21
[1] 23
With the function that I used I got the answer, but I don't know why it is repeated twice.
Add curly braces:
for (i in 1:n) {
if(i %% 2 == 0){
j <- i+3
print(j)
}
}
You can get the same outcome without using the loop:
vec <- 1:20
vec[vec %% 2 == 0] + 3

Adding elements of combinations of vector in a list in R

I am pretty new in R and so what I am trying to do is that I have been given a vector of positive integers like
index <- 1:3
and I want to use this vector to find all the possible combinations of numbers without repetition which I achieve like this
for (i in 1:length(index)) {
combn(index,i)
j = 1
while (j <= nrow(t(combn(index,i)))) {
print(t(combn(index,i))[j,])
j = j + 1
append(comb, j)
}
}
This gives me output as
[1] 1
[1] 2
[1] 3
[1] 1 2
[1] 1 3
[1] 2 3
[1] 1 2 3
But when I create a list comb <- list() and try to append each output as below:
for (i in 1:length(index)) {
combn(index,i)
j = 1
while (j <= nrow(t(combn(index,i)))) {
append(comb, t(combn(index,i))[j,])
j = j + 1
}
}
The problem is it is giving my empty list when I call
comb
list()
I wish to create a list with those elements and use them to retrieve those index rows from a data frame. Do you have any idea how I can achieve this? Any help is welcome. Thanks!
We can use unlist + lapply like below
unlist(
lapply(
seq_along(index),
combn,
x = index,
simplify = FALSE
),
recursive = FALSE
)
which gives
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 1 2
[[5]]
[1] 1 3
[[6]]
[1] 2 3
[[7]]
[1] 1 2 3
This seems to give what you want
index <- 1:3
comb <- list()
for (i in 1:length(index)) {
combn(index,i)
j = 1
while (j <= nrow(t(combn(index,i)))) {
comb <- c(comb, list(t(combn(index,i))[j,]))
j = j + 1
}
}
comb
Output
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 1 2
[[5]]
[1] 1 3
[[6]]
[1] 2 3
[[7]]
[1] 1 2 3
Note that you have to assign your appended list back. Also if you append a list with vector each of the vector element will be a separate element in the new list. You have to wrap that vector in a list() function to append it as one.

split list into lists each of length x

Simple problem, given a list:
main_list <- list(1:3,
4:6,
7:9,
10:12,
13:15)
main_list
# [[1]]
# [1] 1 2 3
# [[2]]
# [1] 4 5 6
# [[3]]
# [1] 7 8 9
# [[4]]
# [1] 10 11 12
# [[5]]
# [1] 13 14 15
I want to split the list into multiple lists where I break up the original one into lists each of length x. So if I said x = 2, I would get 3 lists of length 2, 2 and the leftover 1:
target <- list(list(1:3,
4:6),
list(7:9,
10:12),
list(13:15))
target
# [[1]]
# [[1]][[1]]
# [1] 1 2 3
# [[1]][[2]]
# [1] 4 5 6
# [[2]]
# [[2]][[1]]
# [1] 7 8 9
# [[2]][[2]]
# [1] 10 11 12
# [[3]]
# [[3]][[1]]
# [1] 13 14 15
Something like:
my_split <- function(listtest, x) {
split(listtest, c(1:x))
}
target <- my_split(main_list, 2)
Thanks
here is an option with gl
split(main_list, as.integer(gl(length(main_list), 2, length(main_list))))
It can be converted to a custom function
f1 <- function(lstA, n) {
l1 < length(lstA)
split(lstA, as.integer(gl(l1, n, l1)))
}
EDIT: no conditional logic needed. Just use split() with c() and rep():
my_split <- function(l, x){
l_length <- length(l)
l_div <- l_length / x
split(l, c(rep(seq_len(l_div), each = x), rep(ceiling(l_div), l_length %% x)))
}
my_split(main_list, 2)

Sub-setting elements of a list in R

Assume that this is my list
a <- list(c(1,2,4))
a[[2]] <- c(2,10,3,2,7)
a[[3]] <- c(2, 2, 14, 5)
How do I subset this list to exclude all the 2's. How do I obtain the following:
[[1]]
[1] 1 4
[[2]]
[1] 10 3 7
[[3]]
[1] 14 5
My current solution:
for(j in seq(1, length(a))){
a[[j]] <- a[[j]][a[[j]] != 2]
}
However, this approach feels a bit unnatural. How would I do the same thing with a function from the apply family?
Thanks!
lapply(a, function(x) x[x != 2])
#[[1]]
#[1] 1 4
#
#[[2]]
#[1] 10 3 7
#
#[[3]]
#[1] 14 5
Using lapply you can apply the subset to each vector in the list. The subset used is, x[x != 2].
Or use setdiff by looping over the list with lapply
lapply(a, setdiff, 2)
#[[1]]
#[1] 1 4
#[[2]]
#[1] 10 3 7
#[[3]]
#[1] 14 5

Updating lists in R

I have the following list in R and I want to replace all NULL in the list with zero. Is there a better way of doing this rather than iterating through the list?
$`2014-06-15`
NULL
$`2014-06-16`
[1] 7
$`2014-06-17`
[1] 17
$`2014-06-18`
[1] 24
$`2014-06-19`
[1] 8
$`2014-06-20`
[1] 11
$`2014-06-21`
NULL
$`2014-06-22`
[1] 1
$`2014-06-23`
[1] 20
$`2014-06-24`
[1] 21
In reference to your solution, this way is easier and faster than replacing with a for loop and if statement. Here's a short example.
> ( temp <- list(A = NULL, B = 1:5) )
# $A
# NULL
#
# $B
# [1] 1 2 3 4 5
> temp[sapply(temp, is.null)] <- 0
> temp
# $A
# [1] 0
#
# $B
# [1] 1 2 3 4 5
Nevermind solved it.
temp is my list of dates above
allDates <- names(temp)
for (i in allDates) {
if (is.null(temp[[i]]))
temp[[i]] <- 0
}

Resources