从Python到R-数据帧从字符串

从Python到R-数据帧从字符串,python,r,regex,Python,R,Regex,我有一个Python的工作示例,它接受一个字符串,使用dict理解和正则表达式,最后从中生成一个数据帧: import re, pandas as pd junk = """total=7871MB;free=5711MB;used=2159MB;shared=0MB;buffers=304MB;cached=1059MB; free=71MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;cached=1059MB; cached=1059

我有一个Python的工作示例,它接受一个字符串,使用dict理解和正则表达式,最后从中生成一个数据帧:

import re, pandas as pd

junk = """total=7871MB;free=5711MB;used=2159MB;shared=0MB;buffers=304MB;cached=1059MB;
free=71MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;cached=1059MB;
cached=1059MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;free=109MB;"""

rx = re.compile(r'(?P<key>\w+)=(?P<value>[^;]+)')
records = [{m.group('key'): m.group('value') 
            for m in rx.finditer(line)} 
            for line in junk.split("\n")]
df = pd.DataFrame(records)
print(df)
现在怎么。。。我可以在R做同样的事情吗? 我把lapply和regmatches弄得乱七八糟,但没用。此外,如果缺少值,我将如何执行此操作?

A purrr选项:

图书馆咕噜声 '总数=7871MB;自由=5711MB;已使用=2159MB;共享=0MB;缓冲区=304MB;缓存=1059MB; 免费=71MB;总数=5751MB;共享=3159MB;已使用=5MB;缓冲区=30MB;缓存=1059MB; 缓存=1059MB;总数=5751MB;共享=3159MB;已使用=5MB;缓冲区=30MB;空闲=109MB;'%>% strsplit'\n'%>%.[1]]%>%将行分隔为字符向量 strsplit';'%>%将每行分隔为键值对列表 mapstrsplit,'='%>%将键值对拆分为长度为2的子列表 maptranspose%>%将键值对列表翻转到键值列表 将_-dfr~set_-names.x[[2]],.x[[1]]将值的名称映射到键,并简化为数据帧 >一个tibble:3x6 >缓存的可用共享缓冲区总数 > >17871MB 5711MB 2159MB 0MB 304MB 1059MB >25751MB 71MB 5MB 3159MB 30MB 1059MB >3 5751MB 109MB 5MB 3159MB 30MB 1059MB 或更以数据帧为中心的选项:

图书馆管理员 将文本放入数据框 数据_frametext='总计=7871MB;自由=5711MB;已使用=2159MB;共享=0MB;缓冲区=304MB;缓存=1059MB; 免费=71MB;总数=5751MB;共享=3159MB;已使用=5MB;缓冲区=30MB;缓存=1059MB; 缓存=1059MB;总数=5751MB;共享=3159MB;已使用=5MB;缓冲区=30MB;空闲=109MB;'%>% sep_rowstext,sep='\n'>%将行分隔为单独的行 rowid_to_列的行'>%为每行添加索引以帮助以后扩展 单独的行文本,sep=';'%>%将每行分隔为键值对 filtertext!=%>%从多余的分号中删除额外的条目 separatetext,c'key',value%%>%将键和值分隔为列 spreadkey,值%>%重塑为宽格式 选择“行”下拉“行索引”列 >一个tibble:3x6 >缓存的可用共享缓冲区总数已使用 > >1304MB 1059MB 5711MB 0MB 7871MB 2159MB >2 30MB 1059MB 71MB 3159MB 5751MB 5MB >3 30MB 1059MB 109MB 3159MB 5751MB 5MB 如果您想避免使用包,可以通过read.dcf进行破解,它读取Debian控制格式,如R包描述文件,这只是键值对。DCF使用:代替=和\n代替;,不过,您需要先做一点gsubing:

垃圾邮件[3,]5751MB 109MB 5MB 3159MB 30MB 1059MB 它返回一个矩阵,但格式良好,易于转换为正确的数据帧:

df缓存的可用共享缓冲区总数 >17871MB 5711MB 2159MB 0MB 304MB 1059MB >25751MB 71MB 5MB 3159MB 30MB 1059MB >3 5751MB 109MB 5MB 3159MB 30MB 1059MB 工作示例:

junk <- "total=7871MB;free=5711MB;used=2159MB;shared=0MB;buffers=304MB;cached=1059MB;
free=71MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;cached=1059MB;
cached=1059MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;free=109MB;"

names <- unique(strsplit(gsub("[(?\\n=\\d+MB;)]", " ", a, perl=TRUE), "(\\s+)")[[1]])

dataset <- read.table(text=gsub("[^(\\d+)]", " ", a, perl=TRUE), header = FALSE, col.names=names)

我知道这是可行的,但是你能在答案中解释一下吗?添加了很多评论。如果你穿过每一根管道,你也可以很容易地看到中间产品。这是如何工作的?您想添加一些解释吗?如果列的顺序一致,这种方法会起作用。因为它们不是,所以它是按位置而不是按标签读取数据,这会导致交换值,例如在free和total的第一行和第二行之间。
junk <- "total=7871MB;free=5711MB;used=2159MB;shared=0MB;buffers=304MB;cached=1059MB;
free=71MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;cached=1059MB;
cached=1059MB;total=5751MB;shared=3159MB;used=5MB;buffers=30MB;free=109MB;"

names <- unique(strsplit(gsub("[(?\\n=\\d+MB;)]", " ", a, perl=TRUE), "(\\s+)")[[1]])

dataset <- read.table(text=gsub("[^(\\d+)]", " ", a, perl=TRUE), header = FALSE, col.names=names)