user1665355
user1665355

Reputation: 3393

How to modify values in a list

I have a list:

xxx

[[1]]
[1] 1899   99   99   97   97   97   97   97

[[2]]
[1] 86 86 86 86 86 86 86

[[3]]
 [1] 1897   97   97   97   97   97   97   97   97   97

[[4]]
[1] 3 3 3 3

[[5]]
 [1] 1883   83   83   83   83   83   83   83   83   83

Dput:

list(c(1899L, 99L, 99L, 97L, 97L, 97L, 97L, 97L), c(86L, 86L, 
86L, 86L, 86L, 86L, 86L), c(1897L, 97L, 97L, 97L, 97L, 97L, 97L, 
97L, 97L, 97L), c(3L, 3L, 3L, 3L), c(1883L, 83L, 83L, 83L, 83L, 
83L, 83L, 83L, 83L, 83L))

I then choose the most frequent value in each list element, and repeat that value by the length of the list element:

xxxh=lapply(xxx,function(x) {

  a=max(rle(sort(x))[[1]])

  b=rle(sort(x))[[2]][which(rle(sort(x))[[1]]==a)]

  hh=rep(b,length(x))

  return(hh)

})

I get a warning "In max(rle(sort(x))[[1]]) : no non-missing arguments to max; returning -Inf"

The result is

xxxh
[[1]]
[1] 97 97 97 97 97 97 97 97

[[2]]
[1] 86 86 86 86 86 86 86

[[3]]
 [1] 97 97 97 97 97 97 97 97 97 97

[[4]]
[1] 3 3 3 3

[[5]]
 [1] 83 83 83 83 83 83 83 83 83 83

I then try to paste those values in the list elements above with either 18 or 190 depending on the nchar of the first element of each list element:

xxxm=lapply(xxxh,function(x) {

  kk=x[1]


  if(nchar(kk==0)) {   kk<-0 }

  else {

  if (nchar(kk)==1) {as.numeric(paste(190,kk,sep=""))} else {

  if (nchar(kk)==2) as.numeric(paste(18,kk,sep=""))}}

}

    )

But I only get zeros...

xxxm
[[1]]
[1] 0

[[2]]
[1] 0

[[3]]
[1] 0

[[4]]
[1] 0

[[5]]
[1] 0

I would like to get:

xxxm
[[1]]
[1] 1897

[[2]]
[1] 1896

[[3]]
[1] 1897

[[4]]
[1] 1903

[[5]]
[1] 1883

What am I doing wrong?:(

Best Regards!

Upvotes: 1

Views: 2356

Answers (3)

dickoa
dickoa

Reputation: 18437

You can do something like this too

xxxm <- lapply(xxx,
               function(x) rep(which.max(tabulate(x)), length(x)))

lapply(xxxm, function(x)
       as.numeric(paste0(c(190, 18)[nchar(unique(x))], unique(x))))


[[1]]
[1] 1897

[[2]]
[1] 1886

[[3]]
[1] 1897

[[4]]
[1] 1903

[[5]]
[1] 1883

Upvotes: 2

Ricardo Saporta
Ricardo Saporta

Reputation: 55340

You can simplify the process greatly down to two lines:

Use lapply with table and which.max to get the modes. (statistical modes, not R-language modes)
Then use ifelse to paste accordingly, using the condition if the value is less than 10

# find the most frequent value, using `table` & `which.max` 
mode.mylist <- lapply(mylist, function(x) names(which.max(table(x))))

# paste values as needed.  No need to count characters. Instead check if the value is less than 10. (R coerces to numeric)
ifelse(mode.mylist < 10, paste0("190", mode.mylist), paste0("18", mode.mylist))

[1] "1897" "1886" "1897" "1903" "1883"


Where mylist is your starting list, eg:

mylist <- list(c(1899L, 99L, 99L, 97L, 97L, 97L, 97L, 97L), c(86L, 86L, 86L, 86L, 86L, 86L, 86L), c(1897L, 97L, 97L, 97L, 97L, 97L, 97L, 97L, 97L, 97L), c(3L, 3L, 3L, 3L), c(1883L, 83L, 83L, 83L, 83L, 83L, 83L, 83L, 83L, 83L))

Upvotes: 4

Hong Ooi
Hong Ooi

Reputation: 57686

Your first if(nchar(kk==0)) should be if(nchar(kk)==0).

Upvotes: 3

Related Questions