regex - 我不是来自 grepl 的 gettnig 行号 - 在 R 中执行此操作
问题描述
我正在尝试确定哪一行是数据框中仅包含数字“、”“$”的单元格的第一行:
Assessment Area Offices Offices Deposits as of 6/30/16 Deposits as of 6/30/16 Assessment Area Reviews Assessment Area Reviews Assessment Area Reviews
2 Assessment Area # % $ (000s) % Full Scope Limited Scope TOTAL
3 Ohio County 1 50.0% $24,451 52.7% 1 0 1
4 Hart County 1 50.0% $21,931 47.3% 1 0 1
5 OVERALL 2 100% $46,382 100.0% 2 0 2
此代码确实找到了该行:
grepl("[0-9]",table_1)
但代码返回:
[1] FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
我只想知道行。
解决方案
您的数据可能需要进行一些清理,但这对于解决您的问题并不是完全必要的。您希望找到包含美元符号和适当值的第一行。我的解决方案执行以下操作:
- 迭代行
- 在每一行中,询问是否至少有一个单元格以美元符号开头,后跟数字和逗号的特定组合(将在下面更详细地解释)
- 当我们到达那一行时停止
- 打印行的 ID
该解决方案涉及for
循环、if
语句和正则表达式。
首先,这是我重现数据框的尝试。同样,细节并不重要。我只是想让“钱行”成为第二行,这在您的示例中似乎是这样的
df<- data.frame(
Assessment_Area = c(2,3,4,5),
Offices = c("#",1,1,2),
Dep_Percent_63016 = c("#","50.0%","50.0%","100.0%"),
Dep_Total_63016 = c("$ (000s)", "$24,451", "$21,931","$46,382"),
Assessment_Area_Rev = rep("Blah",4)
)
df
Assessment_Area Offices Dep_Percent_63016 Dep_Total_63016
1 2 # # $ (000s)
2 3 1 50.0% $24,451
3 4 1 50.0% $21,931
4 5 2 100.0% $46,382
Assessment_Area_Rev
1 Blah
2 Blah
3 Blah
4 Blah
这是for
循环:
library(stringr)
for (i in 1:nrow(df)) {
if (any(str_detect(df[i,],"^\\$\\d{1,3}(,\\d{3})*"))) {
print(i)
break
}
}
关键是if
语句的行。如果逻辑向量的任何元素为真,则any
返回。TRUE
在这种情况下,向量是通过应用于stringr::str_detect
索引为 的 df 的一行来创建的df[i,]
。str_detect
返回一个逻辑向量 - 您提供一个字符向量和一个表达式以匹配该向量的元素。它返回TRUE
或FALSE
为向量中的每个元素,在这种情况下是一行中的每个单元格。所以关键是正则表达式:
"^\\$\\d{1,3}(,\\d{3})*"
这是我们在每一行中搜索的模式(货币单元格)。^\\$
表示我们希望字符串以美元符号开头。两个反斜杠转义$
字符,因为它是正则表达式中的元字符(结束锚点)。然后我们想要 1-3 位数字。这将匹配任何低于 1,000 美元的美元价值。然后我们指定表达式可以包含任意数字(包括 0),
后跟三个数字。这将涵盖任何美元价值。
最后,如果我们遇到包含这些表达式之一的行,for
循环将打印行号并结束循环,因此它将返回包含一个所需单元格的最低行号。在此示例中,输出为2
。如果没有遇到适当的行,则不会发生任何事情。
获得这些信息后,您可能还想做更多事情,但如果您只需要包含货币表达式的最低行号,那么这就足够了。
仅查找美元符号、逗号和数字的不太优雅的正则表达式是:
"[0-9$,]+"
这就是您所要求的,尽管我认为这不是您真正想要的,因为这将匹配类似的东西,56$,,$$78