R: Calling objects within character string - r

> foo <- as.character(c(0, 2))
> foo
[1] "0" "2"
> foo[1]
[1] "0"
> foo[2]
[1] "2"
> as.character("0-2")
[1] "0-2" #this is the output I want from the command below:
> as.character("foo[1]-foo[2]")
[1] "foo[1]-foo[2]" # ... was hoping to get "0-2"
I tried some variations of eval(parse()), but same problem. I also tried these simple examples:
> as.character("as.name(foo[1])")
[1] "as.name(foo[1])"
> as.character(as.name("foo[1]"))
[1] "foo[1]"
Any chance of getting something simple like as.character("foo[1]-foo[2]") to display "0-2"?
UPDATE
Similar example (with a much longer string):
> lol <- as.character(seq(0, 20, 2))
> lol
[1] "0" "2" "4" "6" "8" "10" "12" "14" "16" "18" "20"
> c(as.character("0-2"), as.character("2-4"), as.character("4-6"), as.character("6-8"), as.character("8-10"), as.character("10-12"), as.character("12-14"),as.character("14-16"),as.character("16-18"),as.character("18-20"))
[1] "0-2" "2-4" "4-6" "6-8" "8-10" "10-12" "12-14" "14-16" "16-18" "18-20"
I would like to be able to actually call the object lol from within my character string.

We can use paste with the collapse argument
paste(foo, collapse='-')
#[1] "0-2"
If we need to paste adjacent elements together, remove the first and last elements of 'lol' and then paste it together with the sep argument.
paste(lol[-length(lol)], lol[-1], sep='-')
#[1] "0-2" "2-4" "4-6" "6-8" "8-10" "10-12" "12-14" "14-16" "16-18"
#[10] "18-20"

Related

Convert a vector of integers to a vector of strings

toString seems to convert a whole vector to a single string -
toString(c(1,2))
[1] "1, 2"
how does one map the string conversion over each element; i.e. for the above example, to obtain ("1", "2") ?
> as.character(c(1,2))
[1] "1" "2"
Is the output I get from the R-console.
Since the result is a character vector with a single element, the strategy of using as.character will have no effect. Need to use scan:
> scan(text = toString(0:11), sep="," )
Read 12 items
[1] 0 1 2 3 4 5 6 7 8 9 10 11
Then you can use as.character if that is needed:
> res <- scan(text = toString(0:11), sep="," )
Read 12 items
> as.character(res)
[1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11"
I prefer paste0 since it's shorter and (from what I can tell) accomplishes the same thing as as.character:
> paste0(1:2)
[1] "1" "2"
> identical(paste0(1:2),as.character(1:2))
[1] TRUE

extracting text R between special characters

I have multiple strings as shown below:
filename="numbers [www.imagesplitter.net]-0-0.jpeg"
filename1="numbers [www.imagesplitter.net]-0-1.jpeg"
filename2="numbers [www.imagesplitter.net]-19-9.jpeg"
I want the text that appears between the second "-" and the last period.
I would like to get 0,1,9 respectively.
How do I do this? I am not sure how to detect the second "-" and the last period.
Try
sub('^[^-]*-[^-]*-(\\d+)\\..*$', '\\1', files)
#[1] "0" "1" "9"
or
gsub('^[^-]*-[^-]*-|\\..*$', '', files)
#[1] "0" "1" "9"
data
files <- c(filename, filename1, filename2)
I would simply use strsplit to split the strings accordingly here:
sapply(strsplit(files, '[-.]'), '[', 5)
# [1] "0" "1" "9"
Try this:
files=c(filename, filename1, filename2)
sub(".*-(.+)\\.jpeg", "\\1", files)
You could use regmatches function also.
> x <- c("numbers [www.imagesplitter.net]-0-0.jpeg","numbers [www.imagesplitter.net]-0-1.jpeg", "numbers [www.imagesplitter.net]-19-9.jpeg")
> unlist(regmatches(x, gregexpr("^(?:[^-]*-){2}\\K.*(?=\\.)", x, perl=TRUE)))
[1] "0" "1" "9"
You could use the same regex in stringr , str_extract_all function also.
> library(stringr)
> unlist(str_extract_all(x, perl("^(?:[^-]*-){2}\\K.*(?=\\.)")))
[1] "0" "1" "9"
OR
> unlist(str_extract_all(x, perl("(?<=-)[^-.]*(?=\\.)")))
[1] "0" "1" "9"
OR
> unlist(str_extract_all(x, perl(".*-\\K\\d+")))
[1] "0" "1" "9"
you can try
sub("^[^-]+-[^-]+-(.*)\\.[^\\.]*$", "\\1", c(filename, filename1, filename2))
[1] "0" "1" "9"

R: Removing blanks from the list

I'm wondering if there is any way to remove blanks from the list.
As far as I've searched, I found out that there are many Q&As for removing
the whole element from the list, but couldn't find the one regarding
a specific component of the element.
To be specific, the list now I'm working with looks like this:
[[1]]
[1] "1" "" "" "2" "" "" "3"
[[2]]
[1] "weak"
[[3]]
[1] "22" "33"
[[4]]
[1] "44" "34p" "45"
From above, you can find " ", which should be removed.
I've tried different commands like
text.words.bl <- text.words.ll[-which(text.words.ll==" ")]
text.words.bl <- text.words.ll[!sapply(text.words.ll, is.null)]
etc, but seems like " "s in [[1]] of the list still remains.
Is it impossible to apply commands to small pieces in each element of the list?
(e.g. 1, 2, weak, 22, 33... respectively)
I've used "lapply" function to run specific commands to each elements,
and it seemed like those lapply commands all worked....
JY
Use %in%, but negate it with !:
## Sample data:
L <- list(c(1, 2, "", "", 4), c(1, "", "", 2), c("", "", 3))
L
# [[1]]
# [1] "1" "2" "" "" "4"
#
# [[2]]
# [1] "1" "" "" "2"
#
# [[3]]
# [1] "" "" "3"
The replacement:
lapply(L, function(x) x[!x %in% ""])
# [[1]]
# [1] "1" "2" "4"
#
# [[2]]
# [1] "1" "2"
#
# [[3]]
# [1] "3"
Obviously, assign the output to "L" if you want to overwrite the original dataset:
L[] <- lapply(L, function(x) x[!x %in% ""])
Another way would be to use nchar(). I borrowed L from #Ananda Mahto.
lapply(L, function(x) x[nchar(x) >= 1])
#[[1]]
#[1] "1" "2" "4"
#
#[[2]]
#[1] "1" "2"
#
#[[3]]
#[1] "3"

Iterating over characters of string R

Could somebody explain me why this does not print all the numbers separately in R.
numberstring <- "0123456789"
for (number in numberstring) {
print(number)
}
Aren't strings just arrays of chars? Whats the way to do it in R?
In R "0123456789" is a character vector of length 1.
If you want to iterate over the characters, you have to split the string into
a vector of single characters using strsplit.
numberstring <- "0123456789"
numberstring_split <- strsplit(numberstring, "")[[1]]
for (number in numberstring_split) {
print(number)
}
# [1] "0"
# [1] "1"
# [1] "2"
# [1] "3"
# [1] "4"
# [1] "5"
# [1] "6"
# [1] "7"
# [1] "8"
# [1] "9"
Just for fun, here are a few other ways to split a string at each character.
x <- "0123456789"
substring(x, 1:nchar(x), 1:nchar(x))
# [1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
regmatches(x, gregexpr(".", x))[[1]]
# [1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
scan(text = gsub("(.)", "\\1 ", x), what = character())
# [1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
Possible with tidyverse::str_split
numberstring <- "0123456789"
str_split(numberstring,boundary("character"))
1. '0''1''2''3''4''5''6''7''8''9'
Here's a naive approach for iterating a string using a for loop and substring. This isn't any better than existing answers for the common case, but it might be useful if you want to break out of the loop early instead of always traversing the entire string once up front, as str_split/scan/substring(x, 1:nchar(x), 1:nchar(x))/regmatches requires.
s <- "0123456789"
if (s != "") {
for (i in 1:nchar(s)) {
print(substring(s, i, i))
}
}
The if is needed to avoid looping backwards from 1 to 0, inclusive of both ends.
Your question is not 100% clear as to the desired outcome (print each character individually from a string, or store each number in a way that the given print loop will result in each number being produced on its own line).
To store numberstring such that it prints using the loop you included:
numberstring<-c(0,1,2,3,4,5,6,7,8,9)
for(number in numberstring){print(number);}
[1] 0
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
>

How to get empty last elements from strsplit() in R?

I need to process some data that are mostly csv. The problem is that R ignores the comma if it comes at the end of a line (e.g., the one that comes after 3 in the example below).
> strsplit("1,2,3,", ",")
[[1]]
[1] "1" "2" "3"
I'd like it to be read in as [1] "1" "2" "3" NA instead. How can I do this? Thanks.
Here are a couple ideas
scan(text="1,2,3,", sep=",", quiet=TRUE)
#[1] 1 2 3 NA
unlist(read.csv(text="1,2,3,", header=FALSE), use.names=FALSE)
#[1] 1 2 3 NA
Those both return integer vectors. You can wrap as.character around either of them to get the exact output you show in the Question:
as.character(scan(text="1,2,3,", sep=",", quiet=TRUE))
#[1] "1" "2" "3" NA
Or, you could specify what="character" in scan, or colClasses="character" in read.csv for slightly different output
scan(text="1,2,3,", sep=",", quiet=TRUE, what="character")
#[1] "1" "2" "3" ""
unlist(read.csv(text="1,2,3,", header=FALSE, colClasses="character"), use.names=FALSE)
#[1] "1" "2" "3" ""
You could also specify na.strings="" along with colClasses="character"
unlist(read.csv(text="1,2,3,", header=FALSE, colClasses="character", na.strings=""),
use.names=FALSE)
#[1] "1" "2" "3" NA
Hadley's stringi (and previously stringr) libraries are a huge improvement on base string functions (fully vectorized, consistent function interface):
require(stringr)
str_split("1,2,3,", ",")
[1] "1" "2" "3" ""
as.integer(unlist(str_split("1,2,3,", ",")))
[1] 1 2 3 NA
Using stringi package:
require(stringi)
> stri_split_fixed("1,2,3,",",")
[[1]]
[1] "1" "2" "3" ""
## you can directly specify if you want to omit this empty elements
> stri_split_fixed("1,2,3,",",",omit_empty = TRUE)
[[1]]
[1] "1" "2" "3"

Resources