通过字符串解析合并数据帧行

时间:2021-08-03 16:56:09

I'm trying to import into a data frame a conversation with the following structure:

我试图将以下结构的对话导入数据框架中:

conversation<-data.frame(
             uniquerow=c("01/08/2015 2:49:49 pm: Person 1: Hello",
                         "01/08/2015 2:51:49 pm: Person 2: Nice to meet you",
                         "01/08/2015 2:59:19 pm: Person 1: Same here"))

This structure would make it relatively easy to parse the date, time, person and message. But there are a few instances where the message carries a newline, and thus the data frame is miss-structured, like such:

这种结构使解析日期、时间、人员和消息相对容易。但是,有一些实例中消息携带了换行符,因此数据帧是错误结构的,比如:

conversation_errors<-data.frame(
                     uniquerow=c("01/08/2015 2:49:49 pm: Person 1: Hello",
                                 "01/08/2015 2:51:49 pm: Person 2: Nice to meet you",
                                 "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku: ",
                                 "lend me your arms,",
                                 "fast as thunderbolts,",
                                 "for a pillow on my journey."))

How would you go about merging these instances? Is there any package i'm not aware of?

如何合并这些实例?有我不知道的包裹吗?

The desired function would simply recognise the missing structure and "merge" with the preceding row, such that I would get:

所需要的函数只需识别缺失的结构并与前一行“合并”,我就会得到:

conversation_fixed<-data.frame(
                    uniquerow=c("01/08/2015 2:49:49 pm: Person 1: Hello",
                                "01/08/2015 2:51:49 pm: Person 2: Nice to meet you",
                                "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku: lend me your arms, fast as thunderbolts, for a pillow on my journey."))

Any thoughts?

任何想法吗?

2 个解决方案

#1


2  

Assuming that you can correctly identify the properly structured rows using the timestamp (represented below in properDataRegex), then this will do it:

假设您可以使用timestamp(在下面的properDataRegex中表示)正确地标识适当结构的行,那么这将实现:

mydata <- c("01/08/2015 2:49:49 pm: Person 1: Hello",
            "01/08/2015 2:51:49 pm: Person 2: Nice to meet you",
            "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku: ",
            "lend me your arms,",
            "fast as thunderbolts,",
            "for a pillow on my journey.",
            "07/07/2015 3:29:00 pm: Person 1: This is not the most efficient method",
            "but it will get the job done.")

properDataRegex <- "^\\d{2}/\\d{2}/\\d{4}\\s"
improperDataBool <- !grepl(properDataRegex, mydata)
while (sum(improperDataBool)) {
    mergeWPrevIndex <- which(c(FALSE, !improperDataBool[-length(improperDataBool)]) & 
                             improperDataBool)
    mydata[mergeWPrevIndex - 1] <- 
        paste(mydata[mergeWPrevIndex - 1], mydata[mergeWPrevIndex])
    mydata <- mydata[-mergeWPrevIndex]
    improperDataBool <- !grepl(properDataRegex, mydata)
}

mydata
## [1] "01/08/2015 2:49:49 pm: Person 1: Hello"                                                                                                    
## [2] "01/08/2015 2:51:49 pm: Person 2: Nice to meet you"                                                                                         
## [3] "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku:  lend me your arms, fast as thunderbolts, for a pillow on my journey."
## [4] "07/07/2015 3:29:00 pm: Person 1: This is not the most efficient method but it will get the job done."

Here, mydata is a character vector but of course it's now trivial to make into a data.frame as you had in the question, or to parse it using read.table() or read.fwf().

在这里,mydata是一个字符向量,但是现在很容易将它转换为data.frame,或者使用read.table()或read.fwf()解析它。

#2


0  

Here is an alternative approach:

以下是另一种方法:

read.table(text=paste(gsub("(^\\d{2}/\\d{2}/\\d{4}\\s)", "\n\\1", conversation_errors$uniquerow),
                      collapse = " "), sep = "\n", stringsAsFactors = F)[,1]

Which gives:

这使:

[1] "01/08/2015 2:49:49 pm: Person 1: Hello "                                                                                                   
[2] "01/08/2015 2:51:49 pm: Person 2: Nice to meet you "                                                                                        
[3] "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku:  lend me your arms, fast as thunderbolts, for a pillow on my journey."

(Thanks to Ken for the borrowed regex)

(感谢Ken借用regex)

#1


2  

Assuming that you can correctly identify the properly structured rows using the timestamp (represented below in properDataRegex), then this will do it:

假设您可以使用timestamp(在下面的properDataRegex中表示)正确地标识适当结构的行,那么这将实现:

mydata <- c("01/08/2015 2:49:49 pm: Person 1: Hello",
            "01/08/2015 2:51:49 pm: Person 2: Nice to meet you",
            "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku: ",
            "lend me your arms,",
            "fast as thunderbolts,",
            "for a pillow on my journey.",
            "07/07/2015 3:29:00 pm: Person 1: This is not the most efficient method",
            "but it will get the job done.")

properDataRegex <- "^\\d{2}/\\d{2}/\\d{4}\\s"
improperDataBool <- !grepl(properDataRegex, mydata)
while (sum(improperDataBool)) {
    mergeWPrevIndex <- which(c(FALSE, !improperDataBool[-length(improperDataBool)]) & 
                             improperDataBool)
    mydata[mergeWPrevIndex - 1] <- 
        paste(mydata[mergeWPrevIndex - 1], mydata[mergeWPrevIndex])
    mydata <- mydata[-mergeWPrevIndex]
    improperDataBool <- !grepl(properDataRegex, mydata)
}

mydata
## [1] "01/08/2015 2:49:49 pm: Person 1: Hello"                                                                                                    
## [2] "01/08/2015 2:51:49 pm: Person 2: Nice to meet you"                                                                                         
## [3] "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku:  lend me your arms, fast as thunderbolts, for a pillow on my journey."
## [4] "07/07/2015 3:29:00 pm: Person 1: This is not the most efficient method but it will get the job done."

Here, mydata is a character vector but of course it's now trivial to make into a data.frame as you had in the question, or to parse it using read.table() or read.fwf().

在这里,mydata是一个字符向量,但是现在很容易将它转换为data.frame,或者使用read.table()或read.fwf()解析它。

#2


0  

Here is an alternative approach:

以下是另一种方法:

read.table(text=paste(gsub("(^\\d{2}/\\d{2}/\\d{4}\\s)", "\n\\1", conversation_errors$uniquerow),
                      collapse = " "), sep = "\n", stringsAsFactors = F)[,1]

Which gives:

这使:

[1] "01/08/2015 2:49:49 pm: Person 1: Hello "                                                                                                   
[2] "01/08/2015 2:51:49 pm: Person 2: Nice to meet you "                                                                                        
[3] "01/08/2015 2:59:19 pm: Person 1: Same here, let me tell you a haiku:  lend me your arms, fast as thunderbolts, for a pillow on my journey."

(Thanks to Ken for the borrowed regex)

(感谢Ken借用regex)