Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex R:从字符串中删除最后三个点_Regex_R - Fatal编程技术网

Regex R:从字符串中删除最后三个点

Regex R:从字符串中删除最后三个点,regex,r,Regex,R,我有一个文本数据文件,我可能会用readLines阅读它。每个字符串的初始部分都包含大量乱码,后面是我需要的数据。乱七八糟的信息和数据通常用三个点隔开。我想在最后三个点后分割字符串,或者用某种标记替换最后三个点,告诉R将这三个点左边的所有内容都视为一列 下面是一篇关于Stackoverflow的类似文章,它将定位最后一个点: 然而,在我的例子中,一些数据有小数,所以定位最后一个点是不够的。另外,我认为,…在R中有一个特殊的含义,这可能会使问题复杂化。另一个潜在的复杂因素是一些点比其他点大。此外

我有一个文本数据文件,我可能会用
readLines
阅读它。每个字符串的初始部分都包含大量乱码,后面是我需要的数据。乱七八糟的信息和数据通常用三个点隔开。我想在最后三个点后分割字符串,或者用某种标记替换最后三个点,告诉R将这三个点左边的所有内容都视为一列

下面是一篇关于Stackoverflow的类似文章,它将定位最后一个点:

然而,在我的例子中,一些数据有小数,所以定位最后一个点是不够的。另外,我认为,
在R中有一个特殊的含义,这可能会使问题复杂化。另一个潜在的复杂因素是一些点比其他点大。此外,在某些行中,三个点中的一个被逗号替换

除了上面帖子中的
gregexpr
之外,我还尝试过使用
gsub
,但无法找到解决方案

以下是一个示例数据集和我希望实现的结果:

aa = matrix(c(
'first string of junk... 0.2 0 1', 
'next string ........2 0 2', 
'%%%... ! 1959 ...  0 3 3',
'year .. 2 .,.  7 6 5',
'this_string   is . not fine .•. 4 2 3'), 
nrow=5, byrow=TRUE,
dimnames = list(NULL, c("C1")))

aa <- as.data.frame(aa, stringsAsFactors=F)
aa

# desired result
#                             C1  C2 C3 C4
# 1        first string of junk  0.2  0  1
# 2            next string .....   2  0  2
# 3             %%%... ! 1959      0  3  3
# 4                 year .. 2      7  6  5
# 5 this_string   is . not fine    4  2  3
aa=矩阵(c)(
'第一串垃圾…0.2 0 1',
'下一个字符串…….2 0 2',
'%%%... ! 1959 ...  0 3 3',
'年份..2.,.76.5',
“这个字符串不好.•.4 2 3”),
nrow=5,byrow=TRUE,
dimnames=列表(空,c(“C1”))
aa将字符串反转
如有必要,请反转您正在搜索的模式-它不属于您的情况
反转结果

[俳句伪码]

a = 'first string of junk... 0.2 0 1' // string to search
b = 'junk' // pattern to match 

ra = reverseString(a) // now equals '1 0 2.0 ...knuj fo gnirts tsrif'
rb = reverseString (b) // now equals 'knuj'

// run your regular expression search / replace - search in 'ra' for 'rb'
// put the result in rResult
// and then unreverse the result
// apologies for not knowing the syntax for 'R' regex

[/haiku伪代码]

这就成功了,尽管不是特别优雅

a = 'first string of junk... 0.2 0 1' // string to search
b = 'junk' // pattern to match 

ra = reverseString(a) // now equals '1 0 2.0 ...knuj fo gnirts tsrif'
rb = reverseString (b) // now equals 'knuj'

// run your regular expression search / replace - search in 'ra' for 'rb'
// put the result in rResult
// and then unreverse the result
// apologies for not knowing the syntax for 'R' regex
options(stringsAsFactors = FALSE)


# Search for three consecutive characters of your delimiters, then pull out
# all of the characters after that
# (in parentheses, represented in replace by \\1)
nums <- as.vector(gsub(aa$C1, pattern = "^.*[.,•]{3}\\s*(.*)", replace = "\\1"))

# Use strsplit to break the results apart at spaces and just get the numbers
# Use unlist to conver that into a bare vector of numbers
# Use matrix(, nrow = length(x)) to convert it back into a
# matrix of appropriate length
num.mat <- do.call(rbind, strsplit(nums, split = " "))


# Mash it back together with your original strings
result <- as.data.frame(cbind(aa, num.mat))

# Give it informative names
names(result) <- c("original.string", "num1", "num2", "num3")
选项(stringsAsFactors=FALSE)
#搜索分隔符的三个连续字符,然后拉出
#之后的所有角色
#(括号中,用\\1替换)

nums这将让您在大部分时间内都能做到这一点,并且对于包含逗号的数字不会有任何问题:

# First, use a regex to eliminate the bad pattern.  This regex
# eliminates any three-character combination of periods, commas,
# and big dots (•), so long as the combination is followed by 
# 0-2 spaces and then a digit.
aa.sub <- as.matrix(
  apply(aa, 1, function (x) 
    gsub('[•.,]{3}(\\s{0,2}\\d)', '\\1', x, perl = TRUE)))

# Second: it looks as though you want your data split into columns.
# So this regex splits on spaces that are (a) preceded by a letter, 
# digit, or space, and (b) followed by a digit.  The result is a 
# list, each element of which is a list containing the parts of 
# one of the strings in aa.
aa.list <- apply(aa.sub, 1, function (x) 
  strsplit(x, '(?<=[\\w\\d\\s])\\s(?=\\d)', perl = TRUE))  

# Remove the second element in aa.  There is no space before the 
# first data column in this string.  As a result, strsplit() split
# it into three columns, not 4.  That in turn throws off the code
# below.
aa.list <- aa.list[-2]

# Make the data frame.
aa.list <- lapply(aa.list, unlist)  # convert list of lists to list of vectors
aa.df   <- data.frame(aa.list)      
aa.df   <- data.frame(t(aa.df), row.names = NULL, stringsAsFactors = FALSE) 
#首先,使用正则表达式消除错误模式。这个正则表达式
#消除句点、逗号和,
#和大点(•),只要组合后面是
#0-2个空格,然后是一个数字。

aa.sub您能先搜索并将所有逗号和大点替换为常规点吗?我不认为我能将逗号替换为点,因为数据中包含较大数字的逗号:4500。我忘了在我的帖子里提到那件事。虽然也许我可以用点替换逗号,然后在我消除这些乱七八糟的信息后删除数据中的点。值得注意的是,当我试图从Vim发送此代码时,“大点”给我带来了麻烦-但是从网站复制时,它工作得很好。所以我的流程是在Vim中编辑,粘贴到网站,然后粘贴到我的控制台。。。这不对。看起来代码可能正在将数字4、2、3(从最后一个字符串)分配给数据集中的所有5个字符串。@MarkMiller啊,对不起-我使用的是
aa
矩阵,而不是data.frame。如果您想使用data.frame,您可以这样分配
nums
as.vector(gsub(aa$C1,pattern=“^.*[,•]{3}\\s*(.*”,replace=“\\1”))
如果我在第二个字符串的最后一个点和2之间添加一个空格,您可以修改aa.list行来处理它吗?在我的真实数据中,我认为在最后一个点之后总是有一个空格,我只是在创建“aa”时没有意识到。我还可以尝试找出如何修改aa.list.Yes,如果在第二个字符串的最后一个点和之间添加空格,则可以修改第二步中的正则表达式以处理该字符串。这有点棘手,但可行。也就是说,我认为@MattParker有一个更好的主意:首先将每个字符串分为“坏”部分(第一列)和行为良好的部分(数据列)。然后将正则表达式应用于第一列。然后将这两部分重新连接起来。如果这样做,可以使
strsplit
中的正则表达式非常简单。否则,正则表达式将更加复杂。