zmc
2023-08-08 e792e9a60d958b93aef96050644f369feb25d61b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
U
¬ý°d©<ã@sNdZddlmZddlmZddlmZddlZddlZddlZ    ddl
m Z m Z m Z mZddlmZddlmZddlZdd    lmZdd
lmZd Zd Zd ZdZddddddddddddddddgZdZd Zd!Z d"Z!d#e›d$e ›d$e›d$e!›d%    Z"d&e›d$e›d'Z#d(Z$d)d*d+œd,d-„Z%d)d.œd/d0„Z&d1d2„Z'd3d4„Z(Gd5d6„d6eej)ƒZ*dS)7a-
Read a SAS XPort format file into a Pandas DataFrame.
 
Based on code from Jack Cushman (github.com/jcushman/xport).
 
The file format is defined here:
 
https://support.sas.com/content/dam/SAS/support/en/technical-papers/record-layout-of-a-sas-version-5-or-6-data-set-in-sas-transport-xport-format.pdf
é)Ú annotations)Úabc)ÚdatetimeN)ÚCompressionOptionsÚDatetimeNaTTypeÚFilePathÚ
ReadBuffer)ÚAppender)Úfind_stack_level)Ú
get_handle)Ú
ReaderBasezPHEADER RECORD*******LIBRARY HEADER RECORD!!!!!!!000000000000000000000000000000  zKHEADER RECORD*******MEMBER  HEADER RECORD!!!!!!!000000000000000001600000000zPHEADER RECORD*******DSCRPTR HEADER RECORD!!!!!!!000000000000000000000000000000  zPHEADER RECORD*******OBS     HEADER RECORD!!!!!!!000000000000000000000000000000  ÚntypeZnhfunÚ field_lengthZnvar0ÚnameÚlabelZnformZnflZ num_decimalsZnfjZnfillZniformZniflZnifdZnposÚ_z‚Parameters
----------
filepath_or_buffer : str or file-like object
    Path to SAS file or object implementing binary read method.zâindex : identifier of index column
    Identifier of column that should be used as index of the DataFrame.
encoding : str
    Encoding for text data.
chunksize : int
    Read file `chunksize` lines at a time, returns iterator.zBformat : str
    File format, only `xport` is currently supported.z\iterator : bool, default False
    Return XportReader object for reading file incrementally.z#Read a SAS file into a DataFrame.
 
Ú
a
 
Returns
-------
DataFrame or XportReader
 
Examples
--------
Read a SAS Xport file:
 
>>> df = pd.read_sas('filename.XPT')
 
Read a Xport file in 10,000 line chunks:
 
>>> itr = pd.read_sas('filename.XPT', chunksize=10000)
>>> for chunk in itr:
>>>     do_something(chunk)
 
z$Class for reading SAS Xport files.
 
 
Attributes
----------
member_info : list
    Contains information about the file
fields : list
    Contains information about the variables in the file
zÊRead observations from SAS Xport file, returning as data frame.
 
Parameters
----------
nrows : int
    Number of rows to read from data file; if None, read whole
    file.
 
Returns
-------
A DataFrame.
Ústrr)ÚdatestrÚreturncCs.zt |d¡WStk
r(tjYSXdS)z1Given a date in xport format, return Python date.z%d%b%y:%H:%M:%SN)rÚstrptimeÚ
ValueErrorÚpdZNaT)r©rúNd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\pandas/io/sas/sas_xport.pyÚ _parse_date‘sr)ÚscCs@i}d}|D](\}}||||… ¡||<||7}q |d=|S)a
    Parameters
    ----------
    s: str
        Fixed-length string to split
    parts: list of (name, length) pairs
        Used to break up string, name '_' will be filtered from output.
 
    Returns
    -------
    Dict of name:contents of string at given location.
    rr)Ústrip)rÚpartsÚoutÚstartrÚlengthrrrÚ _split_linešs  
r"cCsT|dkrPt t|ƒt d¡¡}t d|›dd|›¡}|j|d}||d<|S|S)NéZS8ÚSz,S©ÚdtypeÚf0)ÚnpÚzerosÚlenr&Úview)ÚvecÚnbytesÚvec1r&Zvec2rrrÚ_handle_truncated_float_vec°s     r/c    Cst d¡}|j|d}|d}|d}|d@}tjt|ƒtjd}d|t |d@¡<d|t |d    @¡<d
|t |d @¡<||L}||?|d @d d
|>B}|dM}||d?d@dd>|dd>|d@BO}tjt|ƒfdd}||d<||d<|jdd}| d¡}|S)zf
    Parse a vector of float values representing IBM 8 byte floats into
    native 8 byte floats.
    z>u4,>u4r%r'Úf1iÿÿÿéi éi@éi€éélÿßéééAiÿélz>f8Zf8)    r(r&r+r)r*Zuint8ÚwhereÚemptyZastype)    r,r&r.Zxport1Zxport2Zieee1ÚshiftZieee2ZieeerrrÚ_parse_float_vecÃs*
          ÿ 
r=c@s’eZdZeZd dddddœd    d
„Zdd œd d „Zdd„Zdd„Zdd œdd„Z    dd œdd„Z
d!dd œdd„Z dd„Z e eƒd"dddœdd„ƒZdS)#Ú XportReaderNú
ISO-8859-1ÚinferzFilePath | ReadBuffer[bytes]z
str | NonerÚNone)Úfilepath_or_bufferÚencodingÚ compressionrcCsf||_d|_||_||_t|d|d|d|_|jj|_z | ¡Wnt    k
r`| 
¡‚YnXdS)NrÚrbF)rCZis_textrD) Ú    _encodingÚ _lines_readÚ_indexÚ
_chunksizer ÚhandlesÚhandlerBÚ _read_headerÚ    ExceptionÚclose)ÚselfrBÚindexrCÚ    chunksizerDrrrÚ__init__ÿs"û
 zXportReader.__init__)rcCs|j ¡dS)N)rJrN©rOrrrrNszXportReader.closecCs|j d¡ ¡S)NéP)rBÚreadÚdecoderSrrrÚ_get_rowszXportReader._get_rowc    CsB|j d¡| ¡}|tkr4d|kr,tdƒ‚tdƒ‚| ¡}ddgddgd    dgd
dgd d gg}t||ƒ}|dd kr|tdƒ‚t|d ƒ|d <||_| ¡}t|dd …ƒ|d<| ¡}| ¡}| t    ¡}|t
k}    |rØ|    sàtdƒ‚t |dd…ƒ}
ddgddgddgddgd    dgd
dgd d gg} t| ¡| ƒ} dd gd
d gddgddgg} |   t| ¡| ƒ¡t| dƒ| d<t| d ƒ| d <| |_ dddœ} t | ¡dd…ƒ}|
|}|drÂ|d|d7}|j |¡}g}d}t|ƒ|
krÌ|d|
…||
d…}}| d¡}t d|¡}ttt|ƒƒ}|d
=| |d |d <|d!}|d dkrv|d"ksb|dkrvd#|›d$}t|ƒ‚| ¡D]2\}}z| ¡||<Wntk
r¬YnXq~||d!7}||g7}qÖ| ¡}|tksætd%ƒ‚||_||_|j ¡|_| ¡|_ d&d'„|jDƒ|_!d(d'„t"|jƒDƒ}t# $|¡}||_%dS))Nrz**COMPRESSED**z<Header record indicates a CPORT file, which is not readable.z#Header record is not an XPORT file.Úprefixr6Úversionr#ZOSrÚcreatedézSAS     SAS     SASLIBz!Header record has invalid prefix.ÚmodifiedzMember header not foundéûÿÿÿéþÿÿÿÚset_nameZsasdataré(ÚtypeÚnumericÚchar)r1r2é6é:rTéŒz>hhhh8s40s8shhh2s8shhl52sr rr2zFloating field width z is not between 2 and 8.zObservation header not found.cSsg|]}|d ¡‘qS)r)rV)Ú.0ÚxrrrÚ
<listcomp>…sz,XportReader._read_header.<locals>.<listcomp>cSs,g|]$\}}dt|ƒdt|dƒf‘qS)rr$r)r)rgÚiÚfieldrrrriˆsÿ)&rBÚseekrWÚ_correct_line1rr"rÚ    file_infoÚ
startswithÚ_correct_header1Ú_correct_header2ÚintÚupdateÚ member_inforUr*ÚljustÚstructÚunpackÚdictÚzipÚ
_fieldkeysÚ    TypeErrorÚitemsrÚAttributeErrorÚ_correct_obs_headerÚfieldsÚ record_lengthÚtellÚ record_startÚ _record_countÚnobsÚcolumnsÚ    enumerater(r&Ú_dtype)rOZline1Zline2ZfifrnZline3Zheader1Zheader2Z    headflag1Z    headflag2ZfieldnamelengthZmemrtÚtypesZ
fieldcountZ
datalengthZ    fielddatarZ
obs_lengthZ
fieldbytesZ fieldstructrkÚflÚmsgÚkÚvÚheaderZdtypelr&rrrrL!sž ÿ"
 
ù    
 
 
 
þ
 " 
 
 
þ
zXportReader._read_headerz pd.DataFramecCs|j|jp ddS)Nr1©Únrows)rUrIrSrrrÚ__next__szXportReader.__next__rrcCsÎ|j dd¡|j ¡|j}|ddkr:tjdtƒd|jdkr\|j |j¡||jS|j dd¡|j d¡}t    j
|t    j d}t      |dk¡}t |ƒdkr¦d}n d    t |ƒ}|j |j¡|||jS)
        Get number of records in file.
 
        This is maybe suboptimal because we have to seek to the end of
        the file.
 
        Side effect: returns file position to record_start.
        rr2rTzxport file may be corrupted.)Ú
stackleveli°ÿÿÿr%l  @@€r#)rBrlrr‚ÚwarningsÚwarnr
r€rUr(Ú
frombufferZuint64Z flatnonzeror*)rOZtotal_records_lengthZlast_card_bytesZ    last_cardÚixZtail_padrrrrƒ’s&     þ
 
   zXportReader._record_countcCs|dkr|j}|j|dS)a
        Reads lines from Xport file and returns as dataframe
 
        Parameters
        ----------
        size : int, defaults to None
            Number of lines to read.  If None, reads whole file.
 
        Returns
        -------
        DataFrame
        NrŽ)rIrU)rOÚsizerrrÚ    get_chunk¸s zXportReader.get_chunkcCsl|jdd}|ddk|ddk@|ddk@}|ddk|dd    k@|dd
kB|dd kB}||M}|S) Nz u1,u1,u2,u4r%r0rÚf2Zf3r'r8éZé_é.)r+)rOr,rŒÚmissZmiss1rrrÚ_missing_doubleÉs $
ÿ
þÿzXportReader._missing_doublez
int | None)rrcsj|dkrˆj}t|ˆjˆjƒ}|ˆj}|dkr>ˆ ¡t‚ˆj |¡}tj    |ˆj
|d}i}t ˆj ƒD]®\}}|dt |ƒ}    ˆj|d}
|
dkrÊt|    ˆj|dƒ}    ˆ |    ¡} t|    ƒ} tj| | <n@ˆj|ddkr
dd    „|    Dƒ} ˆjdk    r
‡fd
d    „| Dƒ} | || i¡qjt |¡} ˆjdkrLt tˆjˆj|ƒ¡| _n |  ˆj¡} ˆj|7_| S) Nr)r&Úcountrr rbrrccSsg|] }| ¡‘qSr)Úrstrip©rgÚyrrrriësz$XportReader.read.<locals>.<listcomp>csg|]}| ˆj¡‘qSr)rVrFr rSrrriîs)r„ÚminrGr€rNÚ StopIterationrBrUr(r”r‡r†r…rrr/rr=ÚnanrFrsrZ    DataFramerHZIndexÚrangerPZ    set_index)rOrÚ
read_linesÚread_lenÚrawÚdataZdf_dataÚjrhr,r rœrŒZdfrrSrrUÔs:
 
 
  zXportReader.read)Nr?Nr@)N)N)Ú__name__Ú
__module__Ú __qualname__Ú_xport_reader_docÚ__doc__rRrNrWrLrrƒr—rr    Ú_read_method_docrUrrrrr>üsún& r>)+r¯Ú
__future__rÚ collectionsrrrvr’Únumpyr(Zpandas._typingrrrrZpandas.util._decoratorsr    Zpandas.util._exceptionsr
ZpandasrZpandas.io.commonr Zpandas.io.sas.sasreaderr rmrprqr~rzZ_base_params_docZ _params2_docZ_format_params_docZ _iterator_docZ _read_sas_docr®r°rr"r/r=ÚIteratorr>rrrrÚ<module>sz           ÿÿÿÿðþýüûýü    9