3

While using flopy that bases some of the functions in the export.shapefile_utils module on pyshp (namely shp2recarray), I've come across a behavior I cannot understand.

Whenever I read some point data shapefile, the records that I can later inspect in Python only show integer values.

I've verified that when writing point shapefiles with pyshp, the Writer class writes only integers values unless the decimal field is specified. Thus, of the following three blocks of code the only one that generates a shape where I can see the decimal figures in the attribute table of the resulting file, is the last one:

w = shapefile.Writer('./test/testfile1')
w.field('X', 'N')
w.field('Y', 'N')
w.field('Z', 'N')
w.point(122.5, 37.5)
w.record(122.5, 37.5, 23.5)
w.close()

w = shapefile.Writer('./test/testfile2')
w.field('X', 'F')
w.field('Y', 'F')
w.field('Z', 'F')
w.point(122.5, 37.5)
w.record(122.5, 37.5, 23.5)
w.close()

w = shapefile.Writer('./test/testfile3')
w.field('X', 'N', decimal=3)
w.field('Y', 'N', decimal=3)
w.field('Z', 'N', decimal=3)
w.point(122.5, 37.5)
w.record(122.5, 37.5, 23.5)

This seems to be consistent with pyshp documentation that states:

Reading Records

A record in a shapefile contains the attributes for each shape in the collection of geometries. Records are stored in the dbf file. The link between geometry and attributes is the foundation of all geographic information systems. This critical link is implied by the order of shapes and corresponding records in the shp geometry file and the dbf attribute file.

The field names of a shapefile are available as soon as you read a shapefile. You can call the "fields" attribute of the shapefile as a Python list. Each field is a Python list with the following information:

Field name: the name describing the data at this column index.
Field type: the type of data at this column index. Types can be:
    "C": Characters, text.
    "N": Numbers, with or without decimals.
    "F": Floats (same as "N").
    "L": Logical, for boolean True/False values.
    "D": Dates.
    "M": Memo, has no meaning within a GIS and is part of the xbase spec instead.
Field length: the length of the data found at this column index. Older GIS software may 
truncate this length to 8 or 11 characters for
"Character" fields.
Decimal length: the number of decimal places found in "Number" fields.

However when creating simple point shapefiles in QGIS with real value fields, in the way depicted by the figure, I only get the integer part of values in each field read when reading the file with pyshp.

enter image description here

Is there any setting I'm missing when creating the shapefile in QGIS that is preventing the decimal part of the fields being read by pyshp?

I'm reading the shapefile with the estandar Reader

sf = shapefile.Reader('./test/somefile')
sf.record(0)
# Out[29]: Record #0: [122, 37, 23]
  • Failing to specify the number of significant digits when creating the 'N' type columns would sensibly generate them with an implicit zero places of precision (whole number). It's difficult to determine what other result you expect. – Vince Nov 6 '20 at 20:39
  • I understand your comment refers to the pyshp code that writes the shapefiles. The problem is that even when I can successfully create point shapefiles in Qgis, with adequate real type fields for point attributes, those are read as integers by pyshp when loading them. – Javgs Nov 7 '20 at 0:30
2

Using string argument in record method solves the problem. I guess, the problem occurs while converting byte, string and float to one another in pyshp module.

import shapefile
w = shapefile.Writer('./test/testfile1')
w.field('X', 'N', decimal=3)
w.field('Y', 'N', decimal=3)
w.field('Z', 'N', decimal=3)
w.point(122.5, 37.5)
w.record("122.5", "37.5", "23.5")
w.close()

enter image description here

sf = shapefile.Reader('./test/testfile1.shp')
sf.record(0)

# Record #0: [122.5, 37.5, 23.5]
  • Thanks for the reply, but again, the problem is in reading common point shapefiles generated in Qgis. The float fields for point attributes are read as integers.The writing code block were provided for exemplification of what can be happening. I can't make pyshp read float values attributes with the reader class. – Javgs Nov 9 '20 at 13:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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