17

I'm creating R code for a Monte Carlo simulation of a professional sport. Because the game dynamics are very complicated and to make the debugging process simpler, I'd like to have R send a line of text for every action that happens in the game to a "log file." The log file would be a comprehensive, play by play description of what's happening in the simulation, and would look something like this…

  • "GAME BEGINS"
  • POSSESSION ASSIGNED TO X TEAM
  • PLAYER Y GETS BALL
  • PLAYER Y SCORES
  • FOUL BY PLAYER Z OCCURS
  • SUBSTITUTION OCCURS (PLAYER W <-> PLAYER Q)
  • "GAME ENDS"

I can't just use the sink() function because while the simulation is running, I setup a progress bar (with the setTxtProgressBar function) and real time scores to be printed to the console. If I used sink(), I couldn't see any of the progress indicators or scores on the R console. Does this make sense? In other words I need to periodically send text to a log file in a cumulative fashion. Here is some example code to give you something to work with…

Thanks

for (i in 1:100)
{**SOMEHOW NEED TO PRINT LINE "START LOOP" TO LOG FILE**;
a <- rnorm(n = 100, mean = i, sd = 5);
print(mean(a)); #PRINT THIS MEAN TO THE CONSOLE
**SOMEHOW PRINT "LOOP 'i' COMPLETE" TO LOG FILE**}
Slyron
  • 784
  • 2
  • 9
  • 21

6 Answers6

17

See ?cat. You can open a file connection to your log file and specify that in your cat call. When you don't specify a file name or connection it will print to the console.

As you say, don't use sink() as it will make the log file the default connection. Rather, open a named connection with file().

> log_con <- file("test.log")
> cat("write to log", file = log_con) # creates file and writes to it
> cat("write to console") # prints to console
write to console

The above results in a log file with the line "write to log" and "write to console" printed on the console.

If you need to append to your log file, set append = TRUE and use the file name instead of the file() connection.

> cat("add to log", file = "test.log", append = TRUE)
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • 1
    This almost does what I need! The only issue is, it doesn't add text to the log file in a cumulative way. That is, every time I run the loop, it clears that log file and when the loop is complete, only the last line remains in the log file. Is there a way to make it cumulative? – Slyron Apr 03 '14 at 17:09
  • See `?cat`. The default for `append` is false, but if you set it to true and use the name of a file instead of a connection it will append (i.e., add cumulatively). – Gregor Thomas Apr 03 '14 at 17:17
  • 1
    Note on file mode: to overwrite the log file each new run use the 'w' mode, to continually append to the same file use the 'a' mode. e.g. log_file = file("fileoutput.log",open = 'w') – JStrahl Sep 24 '18 at 09:58
9

To open the log file in "append" mode:

log_con <- file("test.log",open="a")
BigFinger
  • 1,033
  • 6
  • 7
7

Figured it out, thanks to shujaa and BigFinger. To summarize, here is how you would do it with my example code:

log_con <- file("/filepath/log.txt", open="a")

for (i in 1:100)
{
cat("loop begins", file = log_con, sep="\n")
a <- rnorm(n = 100, mean = i, sd = 5)
print(mean(a))
cat("single loop completed", file = log_con, sep="\n")
}

close(log_con)
Slyron
  • 784
  • 2
  • 9
  • 21
1

The library log4r seems to be more complete than an homemade one: https://github.com/johnmyleswhite/log4r

Jérôme B
  • 420
  • 1
  • 6
  • 25
0

write("this message", file=stderr())

izmirlig
  • 9
  • 4
0

Same example, including values written to the log.txt file:

    log_con <- file("log.txt", open="a")

    for (i in 1:10){
      cat("loop begins; i =", i, '\n', file = log_con)
      a <- rnorm(n = 100, mean = i, sd = 5)
      print(mean(a))
      cat("single loop completed; mean(a) = ", mean(a), '\n', file = 
      log_con)
    } 
    close(log_con)