2016-04-25 56 views
2

我有一个数据框,我试图通过数据框循环来识别那些包含特殊字符或全部是大写字母的列。抓取特殊字符和大写字母的列

我已经尝试了一些东西,但没有任何地方我是苹果来捕捉循环内的列名称。

data = data.frame(one=c(1,3,5,1,3,5,1,3,5,1,3,5), two=c(1,3,5,1,3,5,1,3,5,1,3,5), 
       thr=c("A","B","D","E","F","G","H","I","J","H","I","J"), 
       fou=c("A","B","D","A","B","D","A","B","D","A","B","D"), 
       fiv=c(1,3,5,1,3,5,1,3,5,1,3,5), 
       six=c("A","B","D","E","F","G","H","I","J","H","I","J"), 
       sev=c("A","B","D","A","B","D","A","B","D","A","B","D"), 
       eig=c("A","B","D","A","B","D","A","B","D","A","B","D"), 
       nin=c(1.24,3.52,5.33,1.44,3.11,5.33,1.55,3.66,5.33,1.32,3.54,5.77), 
       ten=c(1:12), 
       ele=rep(1,12), 
       twe=c(1,2,1,2,1,2,1,2,1,2,1,2), 
       thir=c("THiS","THAT34","T(&*(", "!!!","@$#","$Q%J","who","THIS","this","this","this","this"), 
       stringsAsFactors = FALSE) 
data 

colls <- c() 

    spec=c("$","%","&") 
    for(col in names(data)) { 
     if(length(strings[stringr::str_detect(data[,col], spec)]) >= 1){ 
      print("HORRAY") 
colls <- c(collls, col) 
     } 
     else print ("NOOOOOOOOOO") 
    } 


    for(col in names(data)) { 
     if(any(data[,col]) %in% spec){ 
     print("HORRAY") 
colls <- c(collls, col) 
     } 
     else print ("NOOOOOOOOOO") 
    } 

任何人都可以阐明解决这个问题的好方法。

编辑:

的最终目标是有列名的名称的载体,它符合该条件。对不起,我可怜的SO问题,但希望这将是我想要做的

+0

是否有任何意义的数据在列而不是仅仅作为字符串(每行一个字符串)? – Gregor

+0

这就是数据的方式,我也必须通过逻辑,数字等列进行循环。我想我可以提取它们并将其保存为矢量,但是在一天结束时,目标是获取包含特殊字符的变量的列名称,等等 – AGUY

+0

如果包含,通常会得到更好的结果在你的问题中你的“结束的一天”的目标。 – Gregor

回答

1

我会崩溃的数据为字符串(每行一个字符串)

strings = apply(data, 1, paste, collapse = "") 
contains_only_caps = strings == toupper(strings) 
strings[contains_only_caps] 
# [1] "33BB3BBB3.52 212THAT34" "55DD5DDD5.33 311T(&*(" "11EA1EAA1.44 412!!!" "33FB3FBB3.11 [email protected]$#" 
# [5] "55GD5GDD5.33 612$Q%J" "33IB3IBB3.66 812THIS" 


# escaping special characters 
spec=c("\\$","%","\\&") 
contains_spec = stringr::str_detect(strings, pattern = paste(spec, collapse = "|")) 

strings[contains_spec] 
# [1] "55DD5DDD5.33 311T(&*(" "33FB3FBB3.11 [email protected]$#" "55GD5GDD5.33 612$Q%J" 

你也可以上使用which帮助contains_speccontains_only_caps以获得原始数据帧的对应行号。我认为使用字符串而不是逐行数据框元素会更快 - 只要您想要搜索整个字符串,而不是某些条件的特定列。

2

我将使用grep()来搜索您感兴趣的模式。请参阅here

[:upper:]匹配任何大写字母。

将它与锚点(^,$)结合并匹配一次或多次(+)得到^[[:upper:]]+$,并且应该只与大写字母完全匹配。

下面将匹配你的玩具数据集的特殊字符(但不能保证您的真实数据集,即换页匹配所有特殊字符,回车)

[:punct:] #Matches标点 - ! “#$%&'()* +, - 。/:; < => @ [\]^_`{|}〜

注意,而不是使用[:punct:]你可以手动定义特殊字符。?。

我们可以尝试由此得到的代码数据集的第一行:

#Using grepl() rather than grep() so that we return a list of logical values. 
grepl(x= data[1,], pattern = "^[[:upper:]]+$|[[:punct:]]") 
[1] FALSE FALSE TRUE TRUE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE 

这让我们除了九位的值为1.24列我们预期的响应这里小数点被认定为标点符号并被标记为匹配 我们可以添加一个“否定前瞻断言” - (?!\\.) - 在考虑标点符号之前,删除任何考虑时段。请注意,我们使用\来避开这段时间。

grepl(x= data[1,], perl = TRUE, pattern = "(?!\\.)(^[[:upper:]]+$|[[:punct:]])") 
[1] FALSE FALSE TRUE TRUE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE 

这会返回一个更好的响应 - 它现在不再匹配小数位了。注意:这可能不是你想要的,因为这个模式也不会匹配任何字符字段中的全部字符。你需要进一步改进模式。

而不是使用'for循环'在数据框中的每一行重复此代码,我会使用矢量化,而不是'更喜欢'。

要做到这一点,我们必须把我们的脚本转换成一个功能,我们将调用apply()

myFunction <- function(x){ 
     matches <- grepl(x= x, perl = TRUE, pattern = "(?!\\.)(^[[:upper:]]+$|[[:punct:]])") 
    #Given a set of logical vectors 'matches', is at least one of the values true? using any() 
    return(any(matches)) 
} 

apply(X = data, 1, myFunction) 

在1以上指示适用()跨行,而不是列重申。

[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 

在您的示例数据集中,所有行都有一个包含特殊字符或全部大写字母的字符串的条目。这并不令人惊讶,因为您示例数据集中的许多列都是单个大写字母的列表。

如果你只是有兴趣在十三列的值符合规定的标准,你可以使用:

matches <- grepl(x= data$thir, perl = TRUE, pattern = "(?!\\.)(^[[:upper:]]+$|[[:punct:]])") 
matches 
[1] FALSE FALSE TRUE TRUE TRUE TRUE FALSE TRUE FALSE FALSE FALSE FALSE 

于子集上匹配行的数据帧:

data[matches,] 
    one two thr fou fiv six sev eig nin ten ele twe thir 
3 5 5 D D 5 D D D 5.33 3 1 1 T(&*(
4 1 1 E A 1 E A A 1.44 4 1 2 !!! 
5 3 3 F B 3 F B B 3.11 5 1 1 @$# 
6 5 5 G D 5 G D D 5.33 6 1 2 $Q%J 
8 3 3 I B 3 I B B 3.66 8 1 2 THIS 

要在子集的数据帧不匹配的行:

data[!matches,] 
    one two thr fou fiv six sev eig nin ten ele twe thir 
1 1 1 A A 1 A A A 1.24 1 1 1 THiS 
2 3 3 B B 3 B B B 3.52 2 1 2 THAT34 
7 1 1 H A 1 H A A 1.55 7 1 1 who 
9 5 5 J D 5 J D D 5.33 9 1 1 this 
10 1 1 H A 1 H A A 1.32 10 1 2 this 
11 3 3 I B 3 I B B 3.54 11 1 1 this 
12 5 5 J D 5 J D D 5.77 12 1 2 this 

请注意,使用的正则表达式不匹配T HAT34,因为它不是完全由大写字母组成,最终数字为34。

编辑:

要获得列名的识别履行以上描述你的编辑使用myFunction的标准列的列表:

colnames(data)[apply(X = data, 2, myFunction)] 
"thr" "fou" "six" "sev" "eig" "thir" 

数目适用()从1变为2重复跨列而不是行。我们将apply()(逻辑匹配列表(TRUE或FALSE))的输出传递给colnames(数据) - 这会通过子集返回匹配的列名称。

相关问题