检查列表中哪些列具有精确的字符串值,并提取列和行

  • 本文关键字:字符串 提取 列表 r
  • 更新时间 :
  • 英文 :


我有这个数据帧:

df <- data.frame (
A = c("ABC11234","ABC11"),
B = c(11,1),
C = c("11",11),
D =  c(11.1,"11.1"))

我应用这个函数来告诉我哪些行和列有这个确切的字符串,并将输出分配给"a">

a<- lapply(df, function(x) grep("^11$",x))

现在我得到了一个列表,我想:

  1. 提取对(column[name]和row[value](,这样我就可以确切地知道哪一列、哪一行有我在lapply中查找的确切字符串

在上面使用grep的DF示例中,我想知道B=1和C=1,2(例如,列B/行1和列C/行1以及行2的值为"^11$"(

我试过做一些类似于a==integer(0(或unlist(a(的事情,但我被卡住了。

在我看来,您想要的输出只是那些列中包含您想要的"字符串"目前还不清楚是否要避免包含数字11,因为字符串函数会将数字强制转换为字符串。然而,这是我的解决方案,我使用了stringr包而不是基本包。我首先提取所有满足正则表达式的元素(即整个"字符串"是"11"(

library(stringr)
d <- lapply(df, function(x) str_extract_all(x,"^11$"))

这将生成一个长度等于数据帧的列数的列表。列表中的每个元素具有与列中的行相同数量的元素,并且是"11"character(0)。现在,我们获取列表中满足长度大于0的条件的所有元素的索引(即,您想要的字符串至少在列中出现一次(。

lapply(d, function (x) which(x>0))

这将生成另一个长度为4的列表。每个元素都是一个向量,包含满足条件的每列的行#。

让我们取消列出此

e <- unlist(lapply(d, function (x) which(x>0)))

这将生成一个命名向量,其中向量中的项目是行号,名称是列:

B C1 C2 
2  1  2 

为了消除重复的列名(C1、C2等(,我们将再执行一个字符串函数,用列名替换后面跟着字母的任何列名:

names(e) <- str_replace_all(names(e),"([A-Z])\d","\1")

e的输出为:

B C C 
1 1 2 

所有代码加在一起:

library(stringr)
d <- lapply(df, function(x) str_extract_all(x,"^11$"))
lapply(d, function (x) which(x>0))
e<- unlist(lapply(d, function (x) which(x>0)))
names(e) <- str_replace_all(names(e),"([A-Z])\d","\1")
e

还有一个选项是将其重塑为"long"格式,然后获得相应的列名

library(dplyr)
library(tidyr)
library(stringr)
df %>% 
mutate(across(everything(), as.character), row = row_number()) %>%
pivot_longer(cols = -row, names_to = 'col') %>%
group_by(row) %>% 
summarise(col = unique(col[str_detect(value, '^11$')]), .groups = 'drop')
# A tibble: 3 x 2
#    row col  
#  <int> <chr>
#1     1 B    
#2     1 C    
#3     2 C    

我不确定你是否想要下面的

a <- transform(
as.data.frame(
which(matrix(grepl("^11$", as.matrix(df)), nrow = nrow(df)),
arr.ind = TRUE
)),
col = names(df)[col]
)

它给出

> a
row col
1   1   B
2   1   C
3   2   C

我建议使用lapply():

#Data
df <- data.frame (
A = c("ABC11234","ABC11"),
B = c(11,1),
C = c("11",11),
D =  c(11.1,"11.1"),stringsAsFactors = F)
#List
a<- lapply(df, function(x) grep("^11$",x))
#List 2
a[lapply(a,length)==0]

输出:

$A
integer(0)
$D
integer(0)

如果你想从df中提取这些值,你可以这样做:

df[,rownames(do.call(rbind,a[lapply(a,length)==0]))]

输出:

A    D
1 ABC11234 11.1
2    ABC11 11.1

最新更新