我收到了很多看起来像这样的数据:
Even_
Long_var_ longer_var
Obs Var1 name name ...
=================================================
1 xxx 23 lolz ...
2 yyy 34 foo ...
3 zzz 96 bar ...
以SAS的.out文件形式。
如果这些是简单的制表符分隔文件,那就没有问题了,但SAS会做一些神奇的漂亮打印,它会换行变量名称以保持列排列并每隔60或70重复一次标题线条左右。因为变量具有不同的长度(如示例中所示),所以有时这会产生两行变量名称,有时会产生三行,我可以想象会变为四行。
让我们说一下,我无法说服以这种方式提供数据的程序员抛弃一个干净的csv或其他东西。
挑战是3:
我想我可以使用一个很大的愚蠢的多行正则表达式处理三个,但我不知道我如何处理1和2(不是pandas.read_fwf
,至少不是没有足够的预处理,无论如何我已经解决了1和2)。
在pydata宇宙中的某个地方是否已经存在这样做了吗?如果没有,有什么建议吗?
答案 0 :(得分:0)
方法:使用固定宽度变量来提取令人讨厌的变量名称列。一些Lisp代码重构它们。在数据上行进时,使用@(maybe)
通过可选的空行显示来识别标题的重复。如果有,@(skip)
该空行和后续内容直到下一个=====....
。
@(collect)
@{col1-hdr 3}@{col2-var 12}@{col3-var 14}@{col4-var}
@(last)
@/=====.*/
@(end)
@(set (col1-hdr col2-var col3-var col4-var)
@[mapcar (opip (mapcar trim-str) cat-str)
(list col1-hdr col2-var col3-var col4-var)])
@(collect)
@col1 @col2 @col3 @col4
@ (maybe)
@ (skip)
@/=====.*/
@ (end)
@(end)
@(output)
@{col1-hdr 20} @{col2-var 20} @{col3-var 20} @{col4-var}
@ (repeat)
@{col1 20} @{col2 20} @{col3 20} @col4
@ (end)
@(end)
执行命令
$ cat data
Even_
Long_var_ longer_var
Obs Var1 name name
========================================
1 xxx 23 lolz
2 yyy 34 foo
3 zzz 96 bar
Even_
Long_var_ longer_var
Obs Var1 name name
========================================
4 aaa 12 quux
5 bbb 45 xyzzy
6 ccc 78 bork
$ txr data.txr data
Obs Var1 Long_var_name Even_longer_varname
1 xxx 23 lolz
2 yyy 34 foo
3 zzz 96 bar
4 aaa 12 quux
5 bbb 45 xyzzy
6 ccc 78 bork
这个节目作弊!这取决于"最长的varname"是最右边的。如果数据包含较短的行,如$
表示行尾?
longest $
var shorter$
name name shortest$
我们可以做的一件事就是使用空格填充输入流本身直到给定列:确保所有行都填充最多256个字符。 TXR模式语言实际上处理从数据源隐式生成的字符串的惰性列表。我们可以将其重定向到一个明确创建的懒惰列表,我们按摩它。例如,可以通过将此行添加到顶部来完成此操作:
@(next :list @(mapcar* (op format nil "~<256a") (get-lines)))
我们还修改了列收集匹配,以便不在col4
变量中包含尾随空格。
@col1 @col2 @col3 @col4@/ +/
最后,由于我们使用(get-lines)
从标准输入读取(当没有给出参数时),我们使用:
$ txr data.txr < data