Search code examples
pythonrcsvreadr

Python: write CSV with QUOTE_NONNUMERIC, except for None


Given the data ['a', '', None, 5] I would like to write a CSV file as:

"a","",,5

If I use QUOTE_NONNUMERIC, as in:

import csv
with open('eggs.csv', 'w') as csvfile:
    spamwriter = csv.writer(csvfile, quoting=csv.QUOTE_NONNUMERIC)
    spamwriter.writerow(['a', None, 5])

I get

"a","","",5

but if I remove the quoting=csv.QUOTE_NONNUMERIC, I get the unquoted empty string from Nona, but I also lose the quotes around the a and the empty string.

a,,,5

Context: I want to write files that can be read using R readr r: read_csv('eggs.csv', na=c(""), quoted_na=FALSE) that can distinguish between the empty string and missing data.


Solution

  • Using a variation of the answer (and comment) at https://stackoverflow.com/a/11380084/1319998, you can replace None in the data with an instance of:

    class EmptyString(int):
        def __str__(self):
            return ''
    

    then this will be output by Python's csv.writer, using quoting=csv.QUOTE_NONNUMERIC as an unquoted empty string. A fuller example:

    import csv
    
    class EmptyString(int):
        def __str__(self):
            return ''
    EmptyString = EmptyString()
    
    def replace_none_with_emptystring(row):
      return [
        val if val is not None else EmptyString
        for val in row
      ]
    
    with open('eggs.csv', 'w') as csvfile:
        spamwriter = csv.writer(csvfile, quoting=csv.QUOTE_NONNUMERIC)
        spamwriter.writerow(replace_none_with_emptystring(['a', '', None, 5]))
    

    saves

    "a","",,5