Permanently display a time clock in the R command line - r

I am aware of how to add a timestamp during an R session using
R> h <- taskCallbackManager()
R> h$add(function(expr, value, ok, visible) {
+ options("prompt"=format(Sys.time(), "%H:%M:%S> "));
+ return(TRUE) },
+ name = "simpleHandler")
[1] "simpleHandler"
07:25:42> a <- 2
as described in this answer.
How can I make this a permanent feature, so that RStudio always has this as the prompt?

One option is to have a .Rprofile file in the ~/ (usually "C:/Users/me/Documents" in windows), and add the following into it.
It will show time as soon as you do something on the console.
.First <- function(){
h <- taskCallbackManager()
h$add(function(expr, value, ok, visible) {
options("prompt"=format(Sys.time(), "%H:%M:%S> "));
return(TRUE) }, name = "simpleHandler")
}
I think you could do this in the Rprofile.site in your
"C:\Program Files\R\R-x.x.x\etc" as well. As noted by #r2evans, this seems like a bad idea.

Related

Can the R prompt be a time?

?option says this.
‘prompt’: a non-empty string to be used for R's prompt; should
usually end in a blank (‘" "’).
Is it possible to make the prompt to include some dynamic stuffs, e.g., the current time?
You should take a look at the taskCallbackManager (https://developer.r-project.org/TaskHandlers.pdf). With prompt you can call the current time and save it. Example: options("prompt"=format(Sys.time(), "%H:%M:%S> ")). But this is fixed with the time it was set.
The doc for the function taskCallbackManager has the rest:
R> h <- taskCallbackManager()
R> h$add(function(expr, value, ok, visible) {
+ options("prompt"=format(Sys.time(), "%H:%M:%S> "));
+ return(TRUE) },
+ name = "simpleHandler")
[1] "simpleHandler"
07:25:42> a <- 2
07:25:48>
This registers a callback that gets evaluated after each command completes.

I have a problem with a "repeat" function in R

checknames <- function(){
gamers <- c("Rebeca","Luis","Paco")
games <- c("3","2","7")
scores <- c(100,110,50)
table <- data.frame(gamers,games,scores)
r=0
p=0
repeat{
print("Name Player 1: ")
name1=scan(,what="character",1)
for(i in 1:length(gamers)){
if(name1==gamers[i]){
r=readline(prompt = "This player is already in the file. Would you like to change the name? \n 1. Yes \n 2. No \n Select an option: ")
}
}
if(r==2){
break
}
if(r==0){
gamers=c(gamers,name1)
name1 <- data.frame(gamers=name1,games="1",scores="100")
table <- rbind(table,name1)
break
}
}
table
repeat{
print("Name Player 2: ")
name2=scan(,what="character",1)
for(i in 1:length(gamers)){
if(name2==gamers[i]){
print("This player is already in the file. Would you like to change the name?")
r=scan(,what="character",1)
}
}
if(p=="No"){
break
}
if(p==0){
gamers=c(gamers,name2)
name2 <- data.frame(gamers=name2,games="1",scores="100")
table <- rbind(table,name2)
break
}
}
table
}
table <-checknames()
I was doing a code that ask the user 2 names, and it should prove if the table has this name, and if it not, add it, and if it has the name, ask the player if he/she wants to change it.
The problem is that when the player say that he want to change the name, the repeat function do not ever break, I think that is because of I assign something wrong (I assign r==2/r==0) and that is why the repeat function still repeating.
I see a couple of issues with your code. We will focus on the 2nd repeat loop you've written for player 2.
First of all, we can simplify the the for(if( loop you use to check if the name has already been taken. by checking the list all at once instead of looping through the entire index.
if(any(name2==gamers)){
print("This player is already in the file. Would you like to change the name?")
r=scan(,what="character",1)
}
Now, moving on to some of your problems.you store the variable r in your scan but you are checking for the variable p. You should change the line in the above code block to read p=scan(,what="character",1).
Furthermore, you now have a situation where if your user2 put in a name already taken, then changed it to something else, your code will never let them out as you do not have never set p back to 0. This can be adressed by adding an else { p=<-0 } line.
All of the above changes are placed together here for you:
if(any(name2==gamers)){
print("This player is already in the file. Would you like to change the name?")
p=scan(,what="character",1)
} else {
p <- 0}

Use of variable in Unix command line

I'm trying to make life a little bit easier for myself but it is not working yet. What I'm trying to do is the following:
NOTE: I'm running R in the unix server, since the rest of my script is in R. That's why there is system(" ")
system("TRAIT=some_trait")
system("grep var.resid.anim rep_model_$TRAIT.out > res_var_anim_$TRAIT'.xout'",wait=T)
When I run the exact same thing in putty (without system(" ") of course), then the right file is read and right output is created. The script also works when I just remove the variable that I created. However, I need to do this many times, so a variable is very convenient for me, but I can't get it to work.
This code prints nothing on the console.
system("xxx=foo")
system("echo $xxx")
But the following does.
system("xxx=foo; echo $xxx")
The system forgets your variable definition as soon as you finish one call for "system".
In your case, how about trying:
system("TRAIT=some_trait; grep var.resid.anim rep_model_$TRAIT.out > res_var_anim_$TRAIT'.xout'",wait=T)
You can keep this all in R:
grep_trait <- function(search_for, in_trait, out_trait=in_trait) {
l <- readLines(sprintf("rep_model_%s.out", in_trait))
l <- grep(search_for, l, value=TRUE) %>%
writeLines(l, sprintf("res_var_anim_%s.xout", out_trait))
}
grep_trait("var.resid.anim", "haptoglobin")
If there's a concern that the files are read into memory first (i.e. if they are huge files), then:
grep_trait <- function(search_for, in_trait, out_trait=in_trait) {
fin <- file(sprintf("rep_model_%s.out", in_trait), "r")
fout <- file(sprintf("res_var_anim_%s.xout", out_trait), "w")
repeat {
l <- readLines(fin, 1)
if (length(l) == 0) break;
if (grepl(search_for, l)[1]) writeLines(l, fout)
}
close(fin)
close(fout)
}

R: Running computation while waiting for user input

do you see a way to run a computation in R while waiting for a user input?
I'm writing a script that makes differents types of plots which are defined by user input, but in first lot of data has to be loaded and processed. But in fact, user could start defining what he wants already while the processing is running - that's what I would like to do!
I think package Rdsn might provide the functionality that I need, but I was not able to figure out how.
Thanks!
You didn't give me much context, nor reproducible code, so I will just provide a simple example. I am not familiar with the Rdsn package, so I will use provide a solution I know.
# create a function to prompt the user for some input
readstuff = function(){
stuff = readline(prompt = "Enter some stuff: ")
# Here is where you set the condition for the parameter
# Let's say you want it to be an integer
stuff = as.integer(stuff)
if(is.na(stuff)){
return(readstuff())
} else {
return(stuff)
}
}
parameter = readstuff()
print(parameter)
print(parameter + 10)
The key here is to "source" the script instead of "running" it. You can find the "source" button on the top right of RStudio. You can also use source(yourscript) to source it.
So for every parameter you want to prompt the user for input, just call readstuff(). You can also tweak it a little to make it more general. For example:
# create a function to prompt the user for some input
readstuff = function(promptMessage = "stuff", class = "integer"){
stuff = readline(prompt = paste("Enter the", promptMessage, ": "))
# Here is where you set the condition for the parameter
# Let's say you want it to be an integer
stuff = as(stuff, class)
if(is.na(stuff)){
return(readstuff(promptMessage, class))
} else {
return(stuff)
}
}
plotColor = readstuff("plot color", "character")
size = readstuff("size parameter")
xvarName = readstuff("x axis name", "character")
df = data.frame(x = 1:100, y = 1:100)
library(ggplot2)
p = ggplot(df, aes(x = x, y = y, size = size, color = plotColor)) +
labs(x = xvarName) + geom_point()
print(p)
The if(is.na(stuff)) statements won't work if class is character, but I won't get into details on how to fix that, since this question is mainly about how to wait for user input. There are also ways to suppress the warning messages if the user entered something other than what is intended, but again, a bit off topic to talk about it here.
One important thing you have to watch out for is that anything you want R to print or plot, you need to wrap it with a print() function. Otherwise sourcing it won't print nor plot anything. Also, when typing in a parameter that is intended to be a string or character, don't add quotes. For example, for plotColor, type red instead of "red" in the prompt.
Most of the readline code are referenced from here:

How do I run a ldap query using R?

I want to make a query against a LDAP directory of how employees are distributed in departments and groups...
Something like: "Give me the department name of all the members of a group" and then use R to make a frequency analysis, but I can not find any examples on how to connect and run a LDAP query using R.
RCurl seems to have some kind of support ( http://cran.r-project.org/web/packages/RCurl/index.html ):
Additionally, the underlying implementation is robust and extensive,
supporting FTP/FTPS/TFTP (uploads and downloads), SSL/HTTPS, telnet,
dict, ldap, and also supports cookies, redirects, authentication, etc.
But I am no expert in R and have not been able to find a single example using RCurl (or any other R library) to do this..
Right now I am using CURL like this to obtain the members of a group:
curl "ldap://ldap.replaceme.com/o=replaceme.com?memberuid?sub?(cn=group-name)"
Anyone here knows how to do the same in R with RCurl?
Found the answer myself:
First run this commands to make sure RCurl is installed (as described in http://www.programmingr.com/content/webscraping-using-readlines-and-rcurl/ ):
install.packages("RCurl", dependencies = TRUE)
library("RCurl")
And then user getURL with an ldap URL (as described in http://www.ietf.org/rfc/rfc2255.txt although I couldn't understand it until I read http://docs.oracle.com/cd/E19396-01/817-7616/ldurl.html and saw ldap[s]://hostname:port/base_dn?attributes?scope?filter):
getURL("ldap://ldap.replaceme.com/o=replaceme.com?memberuid?sub?(cn=group-name)")
I've written a function here to parse ldap output into a dataframe, and I used the examples provided as a reference for getting everything going.
I hope it helps someone!
library(RCurl)
library(gtools)
parseldap<-function(url, userpwd=NULL)
{
ldapraw<-getURL(url, userpwd=userpwd)
# seperate by two new lines
ldapraw<-gsub("(DN: .*?)\n", "\\1\n\n", ldapraw)
ldapsplit<-strsplit(ldapraw, "\n\n")
ldapsplit<-unlist(ldapsplit)
# init list and count
mylist<-list()
count<-0
for (ldapline in ldapsplit) {
# if this is the beginning of the entry
if(grepl("^DN:", ldapline)) {
count<-count+1
# after the first
if(count == 2 ) {
df<-data.frame(mylist)
mylist<-list()
}
if(count > 2) {
df<-smartbind(df, mylist)
mylist<-list()
}
mylist["DN"] <-gsub("^DN: ", "", ldapline)
} else {
linesplit<-unlist(strsplit(ldapline, "\n"))
if(length(linesplit) > 1) {
for(line in linesplit) {
linesplit2<-unlist(strsplit(line, "\t"))
linesplit2<-unlist(strsplit(linesplit2[2], ": "))
if(!is.null(unlist(mylist[linesplit2[1]]))) {
x<-strsplit(unlist(mylist[linesplit2[1]]), "|", fixed=TRUE)
x<-append(unlist(x), linesplit2[2])
x<-paste(x, sep="", collapse="|")
mylist[linesplit2[1]] <- x
} else {
mylist[linesplit2[1]] <- linesplit2[2]
}
}
} else {
ldaplinesplit<-unlist(strsplit(ldapline, "\t"))
ldaplinesplit<-unlist(strsplit(ldaplinesplit[2], ": "))
mylist[ldaplinesplit[1]] <- ldaplinesplit[2]
}
}
}
if(count == 1 ) {
df<-data.frame(mylist)
} else {
df<-smartbind(df, mylist)
}
return(df)
}
I followed this strategy:
run a Perl script with an LDAP query, write data to disc as JSON.
read in the json structure with R, create a dataframe.
For step (1), I used this script:
#use Modern::Perl;
use strict;
use warnings;
use feature 'say';
use Net::LDAP;
use JSON;
chdir("~/git/_my/R_one-offs/R_grabbag");
my $ldap = Net::LDAP->new( 'ldap.mydomain.de' ) or die "$#";
my $outfile = "ldapentries_mydomain_ldap.json";
my $mesg = $ldap->bind ; # an anonymous bind
# get all cn's (= all names)
$mesg = $ldap->search(
base => " ou=People,dc=mydomain,dc=de",
filter => "(cn=*)"
);
my $json_text = "";
my #entries;
foreach my $entry ($mesg->entries){
my %entry;
foreach my $attr ($entry->attributes) {
foreach my $value ($entry->get_value($attr)) {
$entry{$attr} = $value;
}
}
push #entries, \%entry;
}
$json_text = to_json(\#entries);
say "Length json_text: " . length($json_text);
open(my $FH, ">", $outfile);
print $FH $json_text;
close($FH);
$mesg = $ldap->unbind;
You might need check the a max size limit of entries returned by the ldap server.
See https://serverfault.com/questions/328671/paging-using-ldapsearch
For step (2), I used this R code:
setwd("~/git/_my/R_one-offs/R_grabbag")
library(rjson)
# read into R list, from file, created from perl script
json <- rjson::fromJSON(file="ldapentries_mydomain_ldap.json",method = "C")
head(json)
# create a data frame from list
library(reshape2)
library(dplyr)
library(tidyr)
# not really efficient, maybe thre's a better way to do it
df.ldap <- json %>% melt %>% spread( L2,value)
# optional:
# turn factors into characters
i <- sapply(df.ldap, is.factor)
df.ldap[i] <- lapply(df.ldap[i], as.character)
I wrote a R library for accessing ldap servers using the openldap library.
In detail, the function searchldap is a wrapper for the openldap method searchldap.
https://github.com/LukasK13/ldapr

Resources