11

Can any one tell me, how can I write my output of Fortran program in CSV format? So I can open the CSV file in Excel for plotting data.

5 Answers 5

11

A slightly simpler version of the write statement could be:

write (1, '(1x, F, 3(",", F))') a(1), a(2), a(3), a(4)

Of course, this only works if your data is numeric or easily repeatable. You can leave the formatting to your spreadsheet program or be more explicit here.

2
  • 1
    note you can write the whole array: write(1, '(1x, F, 3(",", F))') a
    – agentp
    Commented Aug 21, 2014 at 20:43
  • I'm trying '(3(i5,","),3(f15.2,","),2(i5,","))' to write a line such as 38,124,1,1,9410.000000,11250.000000,1,1 but I'm getting an error 5006 (for gfortran, that's bad format specifier). What am I doing wrong? I just realized it's probably because I'm trying to write real values as integers (even though they are actually integers)
    – twilsonco
    Commented Feb 24, 2015 at 6:26
10

I'd also recommend the csv_file module from FLIBS. Fortran is well equipped to read csv files, but not so much to write them. With the csv_file module, you put

    use csv_file

at the beginning of your function/subroutine and then call it with:

    call csv_write(unit, value, advance)

where unit = the file unit number, value = the array or scalar value you want to write, and advance = .true. or .false. depending on whether you want to advance to the next line or not.

Sample program:

  program write_csv

    use csv_file

    implicit none

    integer :: a(3), b(2)

    open(unit=1,file='test.txt',status='unknown')

    a = (/1,2,3/)
    b = (/4,5/)

    call csv_write(1,a,.true.)
    call csv_write(1,b,.true.)

  end program

output:

1,2,3

4,5

if you instead just want to use the write command, I think you have to do it like this:

    write(1,'(I1,A,I1,A,I1)') a(1),',',a(2),',',a(3)
    write(1,'(I1,A,I1)') b(1),',',b(2)

which is very convoluted and requires you to know the maximum number of digits your values will have.

I'd strongly suggest using the csv_file module. It's certainly saved me many hours of frustration.

2
  • How do you install flibs? The instruction is not very clear. Commented Jun 1, 2021 at 15:11
  • Hi @bananafish, I've successfully used the module you suggessted but I lose some digits on my ouput file, how can I increase the number precision of exported data?
    – g_don
    Commented Feb 9, 2022 at 10:42
5

The Intel and gfortran (5.5) compilers recognize:

write(unit,'(*(G0.6,:,","))')array or data structure

which doesn't have excess blanks, and the line can have more than 999 columns.

To remove excess blanks with F95, first write into a character buffer and then use your own CSV_write program to take out the excess blanks, like this:

write(Buf,'(999(G21.6,:,","))')array or data structure
call CSV_write(unit,Buf)

You can also use

write(Buf,*)array or data structure
call CSV_write(unit,Buf)

where your CSV_write program replaces whitespace with "," in Buf. This is problematic in that it doesn't separate character variables unless there are extra blanks (i.e. 'a ','abc ' is OK).

3
  • 1
    This is a better answer than the top two at the current point in time.
    – TrippLamb
    Commented Apr 26, 2018 at 18:59
  • My problem is that I have many data structures to print, am I forced to combined them in one single array/structure? Commented Mar 5, 2019 at 7:43
  • I agree this is by far the best answer here. I tested the code with gfortran and it works well there also. I deleted the g95 code for conciseness as it is inferior to the intel/gfortran code and I think interest in g95 code is extremely low and it hasn't been maintained in many years as I understand it. (But if there is disagreement, of course this can be rolled back to include that)
    – JohnE
    Commented Dec 3, 2019 at 20:30
4

I thought a full simple example without any other library might help. I assume you are working with matrices, since you want to plot from Excel (in any case it should be easy to extend the example).

tl;dr

Print one row at a time in a loop using the format format(1x, *(g0, ", "))

Full story

The purpose of the code below is to write in CSV format (that you can easily import in Excel) a (3x4) matrix. The important line is the one labeled 101. It sets the format.

program testcsv
   IMPLICIT NONE 

   INTEGER :: i, nrow
   REAL, DIMENSION(3,4) :: matrix

   ! Create a sample matrix
   matrix = RESHAPE(source = (/1,2,3,4,5,6,7,8,9,10,11,12/), &
                    shape = (/ 3, 4 /))

   ! Store the number of rows
   nrow = SIZE(matrix, 1) 

   ! Formatting for CSV
   101 format(1x, *(g0, ", ")) 
   
   ! Open connection (i.e. create file where to write)
   OPEN(unit = 10, access = "sequential", action = "write", &
        status = "replace", file = "data.csv", form = "formatted") 
   ! Loop across rows
   do i=1,3
      WRITE(10, 101) matrix(i,:)
   end do 
   ! Close connection
   CLOSE(10)


end program testcsv

We first create the sample matrix. Then store the number of rows in the variable nrow (this is useful when you are not sure of the matrix's dimension beforehand). Skip a second the format statement. What we do next is to open (create or replace) the CSV file, names data.csv. Then we loop over the rows (do statement) of the matrix to write a row at a time (write statement) in the CSV file; rows will be appended one after another.

In more details how the write statement works is: WRITE(U,FMT) WHAT. We write "what" (the i-th row of the matrix: matrix(i,:)), to connection U (the one we created with the open statement), formatting the WHAT according to FMT.

Note that in the example FMT=101, and 101 is the label of our format statement:

format(1x, *(g0, ", ")) 

what this does is: "1x" insert a white space at the beginning of the row; the "*" is used for unlimited format repetition, which means that the format in the following parentheses is repeated for all the data left in the object we are printing (i.e. all elements in the matrix's row). Thus, each row number is formatted as: 'g0, ", "'. g is a general format descriptor that handles floats as well as characters, logicals and integers; the trailing 0 basically means: "use the least amount of space needed to contain the object to be formatted" (avoids unnecessary spaces). Then, after the formatted number, we require the comma plus a space: **", ". This produces our comma-separated values for a row of the matrix (you can use other separators instead of "," if you need). We repeat for every row and that's it.

(The spaces in the format are not really needed, thus one could use format(*(g0,","))

Reference: Metcalf, M., Reid, J., & Cohen, M. (2018). Modern Fortran Explained: Incorporating Fortran 2018. Oxford University Press.

1
  • 2
    As with this previous answer using the G edit descriptor, it may be better to use *(g0, :, ", ") (with the colon edit descriptor) to avoid having a trailing , on each line. Commented Jul 19, 2020 at 20:14
1

Tens seconds work with a search engine finds me the FLIBS library, which includes a module called csv_file which will write strings, scalars and arrays out is CSV format.

3
  • 1
    Well surely i went to search online, found better tutorials, but my point of asking is that, the write command can also write to txt format file, I know how to use that, my question is what format i need to follow for CSV format, so when i write out data it is correct
    – aibk01
    Commented Aug 21, 2011 at 2:41
  • So if that was your question then why not actually ask it? There are some clever people who participate on this site, but they are not mind readers........
    – talonmies
    Commented Aug 21, 2011 at 5:41
  • Well i thought you would go around the method and explain that point also, i admit i must have been more clear
    – aibk01
    Commented Aug 21, 2011 at 6:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.