Format function output as a customised multiple lines string - r

I'm trying to make a function which gives output with simple format.
If I already calculated estimated values of beta's, what should I do if I want following result format.
Coefficients
-------------
Constant: 5.2
Beta1: 4
Beta2: 9
Beta3: 2
.
.
.
I tried cat() function but to use cat(), I have to write every line manually like:
cat("Coefficients","\n","-------------","\n","Constant: 5.2","\n","Beta1: 4",....)
Is there any way to make that simple result format?

If you have a vector of 10 results and you want to label them Beta1 to Beta10 you could do:
result = 10:1
b_order = 1:10
paste0("beta", b_order, ": ", result)
This gives:
[1] "beta1: 10" "beta2: 9" "beta3: 8" "beta4: 7" "beta5: 6" "beta6: 5" "beta7: 4" "beta8: 3" "beta9: 2" "beta10: 1"

Related

Output of binaryRatingMatrix in r

I have created a matrix in Excel, of customers and items that have been purchased, by the customers. The column names are "Item 1", "Item 2" ... "Item n" and the row names are "Customer 1", "Customer 2", ... ,"Customer n".
The code is as follows:
library(recommenderlab)
setwd("C:\\Users\\amitai\\Desktop\\se")
USERBASE <- read.csv("USERBASE.csv")
USERBASE2 <- as(USERBASE,"binaryRatingMatrix")
rec <- Recommender(USERBASE2, method = "UBCF")
recommended.items.customer1 <- predict(rec, USERBASE2["customer 1",], n=5)
as(recommended.items.customer1, "list")
I expected to get a list of 5 items, which are most recommended to customer 1.
Instead, I got this output:
$`customer 1`
[1] "1"
After running the same code for customer 103, I got a similar output:
$`customer 103`
[1] "1"
My questions are as follows:
Is there a problem with the code I wrote?
Is there another action I should take after reading the CSV file?
How is the correct output supposed to look like?

odd behavior of print within mapply

I am seeing some unexpected behavior (to me anyway) when print() is included as a side effect in a function wrapped in mapply().
For example, this works as expected (and yes I know it's not how we add vectors):
mapply(function(i,j) i+j, i=1:3, j=4:6) # returns [1] 5 7 9
And so does this:
mapply(function(i,j) paste(i, "plus", j, "equals", i+j), i=1:3, j=4:6)
# returns [1] "1 plus 4 equals 5" "2 plus 5 equals 7" "3 plus 6 equals 9"
But this doesn't:
mapply(function(i,j) print(paste(i, "plus", j, "equals", i+j)), i=1:3, j=4:6)
# returns:
# [1] "1 plus 4 equals 5"
# [1] "2 plus 5 equals 7"
# [1] "3 plus 6 equals 9"
# [1] "1 plus 4 equals 5" "2 plus 5 equals 7" "3 plus 6 equals 9"
What's going on here? I haven't used mapply() in a while, so maybe this is a no-brainer... I'm using R version 3.4.0.
print both prints its argument and returns its value.
p <- print("abc")
# [1] "abc"
p
# [2] "abc"
So each element gets printed, then the vector of stuff gets returned (and printed). Try e.g. invisible(mapply(...)) or m <- mapply(...) for comparison.
FWIW cat() returns NULL ...

generating adjacency table with R

I generated an adjacency table mytable with cosine similarity, m1 is a DTM
cosineSim <- function(x){
as.dist(x%*%t(x)/(sqrt(rowSums(x^2) %*% t(rowSums(x^2)))))
}
cs <- cosineSim(m1)
mytable
"";"1";"2";"3";"4";"5";"6";"7";"8"
"1";0;0;0;0;0;0;0;0
"2";0;0;0;0;0;0;0;0
"3";0;0;0;0.259;0;0;0;0
"4";0;0;0;0;0;0;0;0.324
"5";0;0;0;0;0;0;0;0
"6";0;0;0;0;0;0;0;0
"7";0;0;0;0;0;0;0;0
"8";0;0;0;0;0;0;0;0
When I open it with Gephi, I find that the nodes include all the numbers in the table
Id label
" "
1" 1"
2" 2"
3" 3"
4" 4"
5" 5"
6" 6"
7" 7"
8 8
0 0
0.259 0.259
0.324 0.324
8" 8"
I expected the nodes only include 1-8 as ids, not "", "0 and other numbers. Is there something wrong with my adjacency table?
Remove the double quotes and try to reimport. Since you are using R I would propose to automate your pipeline by using igraph and in your case graph_from_adjacency_matrix, cf here. Then you will need to export the graph in GraphML which Gephi can easily read
Here is some example code for the sake of completeness:
library(igraph)
t <- ';1;2;3;4;5;6;7;8
1;0;0;0;0;0;0;0;0
2;0;0;0;0;0;0;0;0
3;0;0;0;0.259;0;0;0;0
4;0;0;0;0;0;0;0;0.324
5;0;0;0;0;0;0;0;0
6;0;0;0;0;0;0;0;0
7;0;0;0;0;0;0;0;0
8;0;0;0;0;0;0;0;0'
f <- read.csv(textConnection(t), sep = ";", header = T, row.names = 1)
m <- as.matrix(f, rownames.force = T)
colnames(m) <- seq(1:dim(f)[1])
rownames(m) <- seq(1:dim(f)[1])
graph <- graph_from_adjacency_matrix(m, mode=c("directed"), weighted = T)
write.graph(graph, "mygraph.graphml", format=c("graphml") )

add trace/breakpoint while already in R's browser

Edit: for the record, the accepted answer has a significant down-fall in that it re-executes the first n lines of code in the function when re-debugged. This might be okay, but when those lines of code include side-effects (e.g., database updates) and/or long-time calculations, it becomes obvious what is happening. I do not believe R provides the ability to do it "properly" (as some other languages do). Bummer.
Some debuggers allow you to dynamically add breakpoints while in the debugger. Is that functionality possible in R? An example:
quux <- function(..)
{ # line 1
"line 2"
"line 3"
"line 4"
"line 5"
"line 6"
}
trace("quux", tracer = browser, at = 3)
# [1] "quux"
quux()
# Tracing quux() step 3
# Called from: eval(expr, envir, enclos)
# Browse[1]>
# debug: [1] "line 3"
While debugging, I believe I want to jump ahead in the code. Imagine the function has a few hundred lines of code, and I'd prefer to not step through them.
I'd like to be able to do this, and jump from the current line to the next interesting line, but unfortunately it just continues out of the function.
# Browse[2]>
trace("quux", tracer = browser, at = 5)
# [1] "quux"
# Browse[2]>
c
# [1] "line 6"
# # (out of the debugger)
The trace call while in the debugger merely added the breakpoint to the original (global) function, as shown if I immediately call the function again:
quux()
# Tracing quux() step 5
# Called from: eval(expr, envir, enclos)
# Browse[1]>
# debug: [1] "line 5"
I tried setting both at once (at=c(3,5)) while inside the browser, but this just sets those lines for when I exit the debugger and call the function again.
I'm guessing this has to do with the function to which trace is attaching the breakpoint. Looking into trace (and .TraceWithMethods), I think I need to be setting where, but I cannot figure out how to get it to set a new breakpoint/trace on the in-debugging function.
(The larger picture is that I'm troubleshooting a function that is dealing with a kafka-led stream of data. My two options are currently (a) restart the function with the more appropriate trace, but this requires me to purge and restart the data stream as well; or (b) go line-by-line in the debugger, tedious when there are many hundreds of lines of code.)
This may be kind of a solution. First do as in your post:
> quux <- function(..)
+ { # line 1
+ x <- 1 # added for illustration
+ "line 3"
+ "line 4"
+ "line 5"
+ print(x) # added for illustration
+ "line 7"
+ "line 8"
+ }
>
> trace("quux", tracer = browser, at = 4)
[1] "quux"
> quux()
Tracing quux() step 4
Called from: eval(expr, p)
Browse[1]> n
debug: [1] "line 4"
Next, we do as follows in the debugger:
Browse[2]> this_func <- eval(match.call()[[1]]) # find out which funcion is called
Browse[2]> formals(this_func) <- list() # remove arguments
Browse[2]> body(this_func) <- body(this_func)[-(2:4)] # remove lines we have evalutaed
Browse[2]> trace("this_func", tracer = browser,
+ at = 8 - 4 + 1) # at new line - old trace point
Tracing function "this_func" in package "base"
[1] "this_func"
Browse[2]> this_func # print for illustration
function ()
{
"line 5"
print(x)
"line 7"
"line 8"
}
Browse[2]> environment(this_func) <- environment() # change enviroment so x is present
Browse[2]> this_func() # call this_func
[1] 1
[1] "line 8"
The downside is that we end back at "line 5" in the original call to quux after we exit from the call to this_func. Further, we have to keep track of the last at value. We may be able to get this from another function?

how to sort out a nested list in R

The original data was a simple list named "data" like this
[1] "score: 10 / review 1 / ID 1
[2] "score: 9 / review 2 / ID 2
[3] "score: 8 / review 3 / ID 3
----
[30] "score: 7 / review 30 / ID&DATE: 30
In order to sort out scores reviews and ID&DATEs separately,
I first made it a matrix, and then split them by "/" using str_split "stringr"
so the whole process went like this.
a1 <- readLines("data.txt")
a2 <- t(a1) # Matrix
a3 <- t(a2) # reversing rows and columns
b1 <- str_split(a,"/")
here is the problem
b1 came out as a nested list like this.
[[1]]
[1] "score: 10"
[2] "review 1"
[3] "ID 1"
[[2]]
[1] "score: 9"
[2] "review 2"
[3] "ID 2"
[[3]]
[1] "score: 8"
[2] "review 3"
[3] "ID 3"
------
[[30]]
[1] "score: 7"
[2] "review 30"
[3] "ID 30"
I want to extract the values of [[1]][1], [[2]][1], [[3]][1], ... [[30]][1], [[n]][2], and [[n]][3] SEPARATELY, and make each one of them a dataframe.
Any clues?
The following would work for a particular type of nested list that looks like your data. Without a reproducible example, I don't know for sure:
# create nested list
temp <- list(a=c(list("score: 10"), "review 1", "ID 1"),
b=c("score: 9", "review 2", "ID 2"),
c=c("score: 8", "review 3","ID 3"))
# create data frame from this list
df <- data.frame(score=unlist(sapply(temp, function(i) i[1])),
review=unlist(sapply(temp, function(i) i[2])),
ID=unlist(sapply(temp, function(i) i[3])))
I use sapply to pull out elements from each list item. Then, unlist is applied to the output so that it becomes a vector. All of this out put is wrapped in a data.frame. Note that you can rearrange the output so that the variables are arranged differently.
An even cleaner method, mentioned by #parfait, uses do.call and rbind:
# construct data.frame, rbinding each list item
df <- data.frame(do.call(rbind, temp))
# add the desired names
names(df) <- c('score', 'review', 'ID')

Resources