【问题标题】:Modify combination of LaTeX-generated indices into a useful data frame将 LaTeX 生成的索引组合修改为有用的数据框
【发布时间】:2017-08-20 12:52:59
【问题描述】:

我通过 RStudio、.Rnw 脚本、knitrLaTeX 以 PDF 格式输出的几个文档有很长的索引。 readLines可以读入R每个文档的索引(一个“file.ind”文件),我将它们全部组合成一个字符向量。

向量如下所示,但 PDF 文档在 \item 术语(我称之为“主要”术语)下缩进了 \subitem 术语(我称之为“次要”术语)。组合向量有 20 多个主要项(例如 DataStatistics)和 2,000 个次要项(例如'分布、钟形曲线、正态、20)。一个主要术语可以有 5 到 50 多个次要术语。

\item Data
\subitem distribution, bell curve, normal, 20
\subitem absolute number, 111
\subitem arithmetic mean, 21
\subitem big data, 137
\subitem binary, 110
\subitem categorical, 130
\item Statistics
\subitem count, 53
\subitem data, 53, 129
\subitem data, missing, 135
\subitem digits, 53

编程挑战是“填写”初级学期直到下一个初级学期开始,然后填写第二个初级学期直到下一个初级学期开始,依此类推。或者,R 如何创建一个看起来像这样有两列的对象?

Primary Secondary
Data    distribution, bell curve, normal, 20
Data    absolute number, 111
Data    arithmetic mean, 21
Data    big data, 137
Data    binary, 110
Data    categorical, 130
Statistics  count, 53
Statistics  data, 53, 129
Statistics  data, missing, 135
Statistics  digits, 53

我的目标是将修改后的组合索引保存在 Excel 中,以便我可以更轻松地标准化命名约定、检测缺失的术语、修复拼写错误等等。

感谢您的指导。

【问题讨论】:

    标签: r regex latex knitr


    【解决方案1】:

    我认为以下内容应该可以工作(未经全面测试,但大多数部分都经过测试)。您可以逐行读取输入文件,然后处理两种类型的输入:

    • 行以\item 开头
      • 在这种情况下,记录新的主标签,但不要实际上向数据框写入任何内容
    • 行以\subitem 开头
      • 在这种情况下,使用当前行中最新的主要和次要向数据帧写入一行


    df <- data.frame(Primary=character(),
                     Secondary=character(),
                     stringsAsFactors=FALSE) 
    
    # replace 'filepath' with the actual path to your file
    con = file(filepath, "r")
    primary <- NA
    secondary <- NA
    while (TRUE) {
        line <- readLines(con, n=1)
        if (length(line) == 0) {
            break
        }
        if (substr(line, 2, 5) == 'item') {
            primary <- gsub("\\\\item\\s+(.*)", "\\1", line)
        }
        else if (substr(line, 2, 8) == 'subitem') {
            secondary <- gsub("\\\\subitem\\s+(.*)", "\\1", line)
            df$Primary <- primary
            df$Secondary <- secondary
        }
        else {
            print(paste0("Unexpected input: ", line))
        }
    }
    close(con)
    

    请注意,如果您不知道文件的实际路径是什么,则只需在 Windows 资源管理器中查找该文件并复制路径即可。在 Linux 上,您可以使用 grep 查找该文件,或者找到它的位置并输入 pwd

    更新:

    根据您的 cmets,听起来您向我们展示的数据可能已经在字符向量中。您可以将我上面的内容简化为以下内容:

    primary <- NA
    secondary <- NA
    for (i in 1:length(IndxAll)) {
        line <- IndxAll[i]
        if (length(line) == 0) {
            break
        }
        if (substr(line, 2, 5) == 'item') {
            primary <- gsub("\\\\item\\s+(.*)", "\\1", line)
        }
        else if (substr(line, 2, 8) == 'subitem') {
            secondary <- gsub("\\\\subitem\\s+(.*)", "\\1", line)
            df$Primary <- primary
            df$Secondary <- secondary
        }
        else {
            print(paste0("Unexpected input: ", line))
        }
    }
    

    【讨论】:

    • 抱歉,我需要一些关于您的代码的指导。如果我的包含所有组合索引的文件(看起来像我在问题中包含的第一位数据)称为“IndxAll”,为什么我需要再次使用 file() 和 readLines()?
    • 我已经用我认为简洁正确的解决方案回答了您的问题。如果您不喜欢它,您可以等待其他答案或自己尝试。
    • 你的编码能力远超我。我确信答案是简洁和正确的,但是一点解释将极大地帮助我和其他读者能够实施它。我的评论只是为了试图理解你写得如此巧妙的东西。我才到这一步。 con = file(filepath, "r") 文件中的错误(filepath, "r") : object 'filepath' not found
    • @lawyeR 在 Windows 上只需使用文件的绝对路径,例如C:\\users\\lawyer\\input.txt ...除此之外,我的脚本的其余部分应该是抽水和转储。
    • 我明白了;您已经开始使用 .ind 文件(目前有 10 个)。我已经阅读并清理了它们,以便我在问题中复制的是当前格式。您基于 substr() 行,但它在原始 .ind 文件中非常不同。如何使用我的 R 对象作为起点,然后使用与这两个要点相关的代码?
    猜你喜欢
    • 2021-06-10
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 2013-06-19
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多