R script - nchar(x) function is not working in sapply - rscript

when I try to apply an sapply funcion to a data.frame, it does not work and I get this error:
"Error in nchar(x) : 'nchar()' requires a character vector"
the sapply funcion is:
as.data.frame(sapply(df,function(x) nchar(x)))
my test.data frame is:
df<-data.frame(valor1=c("R$ 27.144,22"," 30.035,07 "," 30.761,40 "),valor2=c("17.935,85","13.741,63","19.090,80"),valor3=c("0,00","0,00","1"))
I dont understand why I get that error because I've propperly formated my data frame as follows
df <- as.data.frame(sapply(df,as.character))
what I would want as a result would be a new data.frame were each element is the number of characters of each element in the older data.frame. In my test data.frame example, that would be:
valor1 valor2 valor3
[1]12 9 4
[2]11 9 4
[3]11 9 1

Well the answer lies in the error warning. nchar requires a character vector, which sapply will not provide here (When debugged, the output of sapply is "factor" not "character"). You have to use apply instead:
ncharsap <- function() {
df1 <-data.frame(valor1=c("R$ 27.144,22"," 30.035,07 "," 30.761,40 "),valor2=c("17.935,85","13.741,63","19.090,80"),valor3=c("0,00","0,00","1"))
df1 <- as.data.frame(sapply(df1,as.character))
df2 <- t(as.data.frame(apply(df1,1, function(x) nchar(x))))
return(df2)
}
Note: It is not good practice to use built-in function names for naming custom objects. So I changed df to df1. And also the output requires transpose by t to confirm with your required output.

Related

haskell reading and iterating

I need your help guys.
Im trying to learn and do a simple task in haskell, but it's still hard for me.
What im trying to do is: Read a line of numbers separated with whitespace, iterate over that list, check values, and if values are not zero add 1 otherwise -1. I was trying to do it watching some tutorials and other project code, but it just outputs a bunch of errors.
My code:
import System.Environment
import Control.Monad
import Text.Printf
import Data.List
import System.IO
solve :: IO ()
solve = do
nums <- map read . words <$> getLine
print (calculate nums)
calculate (x:xs) = x + check xs
check num
| num == 0 =
-1
| otherwise =
1
main :: IO ()
main = do
n <- readLn
if n /= 0
then do
printf "Case: "
solve
else main
Errors:
C:\Users\Donatas\Documents\haskell\la3.hs:9:21: error:
* Ambiguous type variable `b0' arising from a use of `read'
prevents the constraint `(Read b0)' from being solved.
Probable fix: use a type annotation to specify what `b0' should be.
These potential instances exist:
instance Read BufferMode -- Defined in `GHC.IO.Handle.Types'
instance Read Newline -- Defined in `GHC.IO.Handle.Types'
instance Read NewlineMode -- Defined in `GHC.IO.Handle.Types'
...plus 25 others
...plus six instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the first argument of `map', namely `read'
In the first argument of `(.)', namely `map read'
In the first argument of `(<$>)', namely `map read . words'
|
9 | nums <- map read . words <$> getLine
| ^^^^
C:\Users\Donatas\Documents\haskell\la3.hs:10:9: error:
* Ambiguous type variable `a0' arising from a use of `print'
prevents the constraint `(Show a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Show HandlePosn -- Defined in `GHC.IO.Handle'
instance Show BufferMode -- Defined in `GHC.IO.Handle.Types'
instance Show Handle -- Defined in `GHC.IO.Handle.Types'
...plus 27 others
...plus 13 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In a stmt of a 'do' block: print (calculate nums)
In the expression:
do nums <- map read . words <$> getLine
print (calculate nums)
In an equation for `solve':
solve
= do nums <- map read . words <$> getLine
print (calculate nums)
|
10 | print (calculate nums)
| ^^^^^^^^^^^^^^^^^^^^^^
C:\Users\Donatas\Documents\haskell\la3.hs:12:1: error:
* Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
* When checking the inferred type
calculate :: forall a. (Eq a, Num [a], Num a) => [a] -> a
|
12 | calculate (x:xs) = x + check xs
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
To start with, I suggest you default to always writing type annotations. And before you start implementing anything, sketch out what the types of your program look like. For this program I suggest you start from:
main :: IO ()
solve :: String -> String
calculate :: [Int] -> Int
check :: Int -> Int
The names could also probably be improved to better convey what it is they're doing.
Note that there is only one function with type IO _. This serves to isolate the impure part of your program, which will make your life easier (e.g. testing, code reasoning, etc).
You're not far off. Just try reworking your code to fit into the above types. And be aware that you're missing a pattern in your calculate implementation ;)
If you inspect your code and follow the types, it is crystal-clear where the error is. Yes, you can add type annotations -- that is highly recommended -- but I find your code is so simple you could get away with just a bit of equational reasoning.
It starts with solve, it is easy to see that nums is of type Read a => [a], given that you split a string by words (i.e. [String]) and map read over it. So a list of as is what you give to calculate. As you know, a list is the disjoint sum between (1) the empty list ([]) and (2) a cons cell made of a head, an element of type a, and a tail, the rest of the list ((x:xs)).
First thing you notice is that the case of the empty list is missing; let's add it:
calculate [] = 0 -- I assume this is correct
On to the body of calculate and check. The latter clearly expects a number, you can be a bit more concise by the way:
check 0 = -1
check _ = 1
Now if you look at calculate, you see that you are calling check and passing it xs. What is xs? It is bound in the pattern (x:xs) which is how you uncons a cons cell. Clearly, xs is the tail of the cell and so a list itself. But check expects a number! The only number you can expect here is x, not xs. So let's change you code to
calculate (x:xs) = check x + ...
Your specifications state that you want to iterate over the list. That can only happen if you do something with xs. What can you do with it? The only answer to that is to call calculate recursively:
calculate (x:xs) = check x + calculate xs
... and with these changes, your code is fine.

R Multiplying each element of an array by a different number

I am trying to multiply each element of an array by an integer (along the first dimension). The tricky thing is that this integer will change for each element.
An example :
test <- array(dim = c(3,5,7))
test[1,,] <- 1
test[2,,] <- 10
test[3,,] <- 100
vec <- c(1,2,3)
The result I want is an array with the same dimension (3,5,7) and along the first dimension :
test[1,,] * vec[1]
test[2,,] * vec[2]
test[3,,] * vec[3]
This means
Result <- array(dim = c(3,5,7))
Result[1,,] <- 1
Result[1,,] <- 20
Result[1,,] <- 300
I think I am quite close with different functions like outer or apply but I think there is an easier way, as I have a lot of data to treat. For now, I found the outer function, and I should select something like the diagonal of the result.
Can someone help ?
slice.index might be helpful here
Result <- test * vec[slice.index(test, 1)]
How about
test*replicate(7, replicate(5, vec))
What's wrong with using apply like this?
sapply(1:length(vec), function(i) test[i,,]<<- test[i,,]*vec[i])
In this case you can just do
Result <- test*vec
Note that this will only work if the dimension that is being split and multiplied is the first one.

String as input variable - R

I try to figure out how to solve this problem. I want to store different elements into an array such as xtrain1, xtrain2... xtrainN by using the paste() and seq() method. Also these elements represents a variable, which should be applied to the array function. The idea is to create a string of these elements and parse it to the array function, which recognized that this string are variables inside the function. Creating the vector seq_Xtrain it creates the elements for a desired number of logValues (e.g. 10) in a string. If I apply the different elements directly to the array function it works. I think the extraction of the elements inside the string does not work. Would be nice if someone can help me, thanks!
seq_Xtrain <- paste("xtrain", seq(from=1, to=logValue),sep="", collapse=", ")
### Output of seq_Xtrain
[1] "xtrain1, xtrain2, xtrain3, xtrain4, xtrain5, xtrain6, xtrain7, xtrain8, xtrain9, xtrain10"
x_train <<- array( c(seq_Xtrain), dim=c(dim(xtrain1),logValue))
####### For example this works
##x_train <<- array( c(xtrain1, xtrain2, xtrain3, xtrain4,xtrain5, xtrain6,
## xtrain7, xtrain8,xtrain9, xtrain10, xtrain11, xtrain12,
## xtrain13, xtrain14, xtrain15, xtrain16,xtrain17, xtrain18, xtrain19, xtrain20), dim=c(dim(xtrain1),20))
### Received output
> x_train[2]
[1] "xtest1, xtest2, xtest3, xtest4, xtest5, xtest6, xtest7, xtest8, xtest9, xtest10, xtest11, xtest12, xtest13, xtest14, xtest15, xtest16, xtest17, xtest18, xtest19, xtest20"
### Desired Output
> x_train[2]
[1] 0.4444944
I am not 100% sure what you want to do also because some reproducible sample data is missing. But look at this example where I use get:
logValue <- log(1:3)
xtrain1 <- log(1)
xtrain2 <- log(2)
xtrain3 <- log(3)
seq_Xtrain <- paste0("xtrain", 1:length(logValue))
x_train <- array(sapply(seq_Xtrain, get))
Get looks for objects of the desired name and retrieves their value. In this case this yields
> x_train
[1] 0.0000000 0.6931472 1.0986123

Finding specific values in an array

I am relatively new to R programming. I am writing a code that generates an array of numbers:
[1] 0.5077399, 0.4388107, 0.3858783, 0.3462711, 0.3170844, 0.2954411, 0.2789464, 0.2658839,
[9] 0.2551246, 0.2459498
Note: I manually separated the values by commas for ease on the eyes :)
I want to pick the first 3 numbers from this array that are below 0.3 - [0.2954411, 0.2658839, 0.2551246]. In addition to picking these values, I want to generate the numbers that represents where those three values exist within the array. In this case, I want the code to give me [6,7,8].
How would I write code to do this?
I greatly appreciate the help.
For a similar simulated set,
y <- c(2, 4,6, 8)
ind <- which(y < 6) ## for finding indices 1 and 2
val <- y[y<6] ## for picking values 2 and 4

google spreadsheet: join arrays using function NOT CODE

I have one array
1
2
3
another array
4
5
6
How do I use one function to join the 2 arrays?
1
2
3
4
5
6
Let's say your arrays are:
A1:A3 = {1;2;3} and B1:B3 = {4;5;6}
Write somewhere: ={A1:A3;B1:B3}
Semicolons ; are used to separate rows, and commas , are for columns.
Here is the documentation: Using arrays in Google Sheets
TRANSPOSE() //takes matrix as argument and returns transposed matrix
SPLIT() //breaks apart a string based on a delimiter character (char(13) here)
ARRAYFORMULA() //applies the formula within to array vs cell
CONCATENATE() //joins each cell in each range with a char(13), then the next cell...then the next matrix of cells (to which the first process also happens)
//note char(13) is a carriage return, i will call CR for ease
so if you have matrix A : 1, 2, 3
and matrix B : 4, 5, 6
the steps would look like this:
TRANSPOSE(SPLIT(ARRAYFORMULA(CONCATENATE("1CR2CR3CR" ; "4CR5CR6CR")), CR))
TRANSPOSE(SPLIT("1CR2CR3CR4CR5CR6CR", "CR"))
TRANSPOSE({"1","2","3","4","5","6"})
finally:
1
2
3
4
5
6
=FLATTEN(A1:A3,B1:B3) should do the trick
=filter({A1:A;B1:B}, {A1:A;B1:B}<>"")
I'm noticing this is an older question, so this might not have existed when previous responses were written.
You're looking for the JOIN() formula.
(Documentation link)
Sample Usage
JOIN(" and-a ",{1,2,"1 2 3 4"})
JOIN(",",{1,2,3},{4;5;6})
JOIN("-",A1:A100)
Syntax
JOIN(delimiter, value_or_array1, [value_or_array2, ...])
delimiter - The character or string to place between each concatenated value.
delimiter may be specified as blank, e.g. JOIN(,{1,2,3}).
value_or_array1 - The value or values to be appended using delimiter.
value_or_array2, ... - [ OPTIONAL ] - Additional value or array to be appended using delimiter.
Given the information provided by Mr.Monshaw, I figured this out for you.
Given values "1,2,3" are in cells A1:A3 of a spreadsheet, and values "4,5,6,7" are in cells B1:B4. Here is the formula to use:
=TRANSPOSE(SPLIT(ARRAYFORMULA(CONCATENATE(concat(A1:A3,",");concat(B1:B4,","))),","))
Explanation.
The concat formula creates a string of the values with the indicated separator, ",". So concat(A1:A3,",") results in "1,2,3".
The Concatenate combines the values of the specified array as one string. So CONCATENATE(concat(A1:A3,",");concat(B1:B4,",")) results in "1,2,3,4,5,6,7"
The Split function here is used to identify the "," as a deliminator and not a value in the array. The Transpose will cause the results to display in a column instead of in a row.
I found this even easier...
=ARRAYFORMULA({A:A;B:B})

Resources