I generated a file which contains a logical value either a "TRUE" or a "FALSE" on each line. Now I would like to read the logical data from the file into R. However the data that are read in are of mode "character" not logical values. I was wondering how to read the data as logical values from the file.
My R code is
cat(FALSE,"\n", file="1.txt", append=FALSE);
for (i in 2:5) cat(TRUE,"\n",file="1.txt", append=TRUE);
a=scan(file="1.txt", what="logical")
The output is:
> mode(a)
[1] "character"
> mode(a[1])
[1] "character"
> a[1]
[1] "FALSE"
I want a[1] to be logical value.
Thanks and regards!
Ah, now I get it. You have to read ?scan very carefully to see that what you've done is not what scan() wants for the what argument. I missed this first time and then wondered why your code wasn't working. This is the key section:
what: the type of ‘what’ gives the type of data to be read. The
supported types are ‘logical’, ‘integer’, ‘numeric’,
‘complex’, ‘character’, ‘raw’ and ‘list’.
and the key phrase is type. So you need to pass an object of the correct type to argument what.
In your example:
> typeof("logical")
[1] "character"
So scan() reads in an object of type "character".
The solution is simply to use what = TRUE, or indeed anything that R considers a logical (see comments to this answer), instead
> typeof(TRUE)
[1] "logical"
> ## or
> typeof(logical())
[1] "logical"
## So now read in with what = TRUE
> a <- scan(file="1.txt", what = TRUE)
Read 5 items
> class(a)
[1] "logical"
> typeof(a)
[1] "logical"
read.table() is more logical in how you tell it what the data to be read in are. The equivalent call there would be:
> b <- read.table("1.txt", colClasses = "logical")[,]
> class(b)
[1] "logical"
> typeof(b)
[1] "logical"
HTH
Use a=='TRUE'->a.
Related
I have this simple dataset
https://www.mediafire.com/file/ntmu0tvtpm73h2i/data.xlsx/file
library(readxl)
library(VarSelLCM)
data <- read_xlsx("C:/User/data.xlsx")
data$type <- as.factor(data$type)
data$T3 <-as.integer(data$T3)
data$T5 <-as.integer(data$T5)
data$T14 <-as.integer(data$T14)
data$T15 <-as.integer(data$T15)
data$T18 <-as.integer(data$T18)
data$T22 <-as.integer(data$T22)
When I run lapply(data, class)
I get
$`T3`
[1] "integer"
$T5
[1] "integer"
$T14
[1] "integer"
$T15
[1] "integer"
$T18
[1] "integer"
$T22
[1] "integer"
$type
[1] "factor"
So everything seems to be OK.
But when I run
res_with <- VarSelCluster(data, gvals = 1:4, nbcores = 1, crit.varsel = "BIC")
I get the Error
Error in VSLCMdataMixte(x) :
At least one variable is neither numeric, integer nor factor!
The problem perhaps could be that when I run
> print(typeof(data$type))
I get this:
[1] "integer"
So it seems that data$type is integer?? though I converted it to factor? And it indeed is a factor as shown by lapply??
But even if the data$type variable was integer, it should be correct for VarSelCluster, because it requires integer variables, this is totally confusing.
How could I solve this?
VarSelCluster requires data as a data.frame, so first you need to set class(data)="data.frame"
How do I change the typeof of one object a to another object b
without explicitly specifying the type
a <- letters
b <- as.factor(a)
typeof(a)
#> [1] "character"
So I would like to convert b to typeof(a), but without explicitly
using as.character, because in another instance a might be e.g.
integer. This obviously does not work:
typeof(b) <- typeof(a)
The closest I could come is, but not sure if there's any better solution.
a <- '1'
b <- 2
a <- unlist(lapply(a,paste0('as.',class(b))))
a
a <- '245'
a <- unlist(lapply(a,paste0('as.',class(b))))
a
Output:
> a
[1] 245
Similar answer to #amrrs except I think you may want this functionality to be used programtically, and when converting types of an object you may get errors that return NA's - which is unwanted behaviour - when you try and convert variables that cannot be coerced to another data type.
The below function accounts for this based on R's coercion rules. (Assuming you want to be using class() and not typeof())
convertClass <- function(object1, object2){
logic=c("logical", "integer", "numeric", "complex", "character", "list")
ifelse(match(class(object1), logic) < match(class(object2), logic),
eval(parse(text=paste0('as.',class(object2),"(",object1,")"))),
paste0("convertClass() cannot convert type ", class(object1), " to ", class(object2))
)
}
> convertClass(1,'1')
[1] "1"
> convertClass('1', 1)
[1] "convertClass() cannot convert type character to numeric"
Using this loses the functionality of converting "1" to 1 for example, which can be coerced in R, but does provide a strict safeguard if you don't know the type of a variable that you are feeding the function.
I have a dataframe "c1" with one column as "region".
sum(is.na(c1$region))
[1] 2
class(c1$region)
[1] "factor"
However, when I use paste()
f1<-paste("c1","$","region",sep="")
> f1
[1] "c1$region"
> sum(is.na(f1))
[1] 0
I tried as.name(f1) and as.symbol(f1). Both convert f1 to the "name" class. noquote(f1) converts the char[1] element to the "noquote" class.
> f2<-as.name(f1)
> f2
`c1$region`
> sum(is.na(f2))
[1] 0
Warning message:
In is.na(f2) : is.na() applied to non-(list or vector) of type 'symbol'
> class(f2)
[1] "name"
I want to retain the class of c1$region while being able to use it in queries such as sum(is.na(f2)). Please help.
I'm not 100% sure I understand what you are trying to do, but maybe this will help:
c1 <- data.frame(region=c(letters[1:3], NA))
clust <- 1
variable <- "region"
f1 <- get(paste0("c", clust))[[variable]] # <--- key step
class(f1)
# [1] "factor"
sum(is.na(f1))
# [1] 1
In the key step, we use get to fetch the correct cluster data frame using its name as a character vector, and then we use [[, which unlike $, allows us to use a character variable to specify which column we want.
I have found something odd today, I wanted to ask you if there was a logical reason for what I am seeing, or if you think this is a bug that should be reported to the R-devel team:
df <- data.frame(a = 1L:10L)
class(df$a)
# [1] "integer"
m <- as.matrix(df)
class(m[, "a"])
# [1] "integer"
No surprise so far: as.matrix preserves the data mode, here "integer". However, with an empty (no rows) data.frame:
df <- data.frame(a = integer(0))
class(df$a)
# [1] "integer"
m <- as.matrix(df)
class(m[, "a"])
# [1] "logical"
Any idea why the mode changes from "integer" to "logical" here? I am using version 2.13.1
Thank you.
This is because of this one line in as.matrix.data.frame:
if (any(dm == 0L)) return(array(NA, dim = dm, dimnames = dn))
Basically, if any dimensions are zero, you get an array "full" of NA. I say "full" because there aren't really any observations because one of the dimensions is zero.
The reason the class is logical is because that's the class of NA. There are special NA for other classes, but they're not really necessary here. For example:
> class(NA)
[1] "logical"
> class(NA_integer_)
[1] "integer"
> class(NA_real_)
[1] "numeric"
> class(NA_complex_)
[1] "complex"
> class(NA_character_)
[1] "character"
I manage to do the following:
stuff <- c("banana_fruit","apple_fruit","coin","key","crap")
fruits <- stuff[stuff %in% grep("fruit",stuff,value=TRUE)]
but I can't get select the-not-so-healthy stuff with the usual thoughts and ideas like
no_fruit <- stuff[stuff %not in% grep("fruit",stuff,value=TRUE)]
#or
no_fruit <- stuff[-c(stuff %in% grep("fruit",stuff,value=TRUE))]
don't work. The latter just ignores the "-"
> stuff[grep("fruit",stuff)]
[1] "banana_fruit" "apple_fruit"
> stuff[-grep("fruit",stuff)]
[1] "coin" "key" "crap"
You can only use negative subscripts with numeric/integer vectors, not logical because:
> -TRUE
[1] -1
If you want to negate a logical vector, use !:
> !TRUE
[1] FALSE
As Joshua mentioned: you can't use - to negate your logical index; use ! instead.
stuff[!(stuff %in% grep("fruit",stuff,value=TRUE))]
See also the stringr package for this kind of thing.
stuff[!str_detect(stuff, "fruit")]
There is also a parameter called 'invert' in grep that does essentially what you're looking for:
> stuff <- c("banana_fruit","apple_fruit","coin","key","crap")
> fruits <- stuff[stuff %in% grep("fruit",stuff,value=TRUE)]
> fruits
[1] "banana_fruit" "apple_fruit"
> grep("fruit", stuff, value = T)
[1] "banana_fruit" "apple_fruit"
> grep("fruit", stuff, value = T, invert = T)
[1] "coin" "key" "crap"