R:找到匹配的字符串,然后复制行

R:找到匹配的字符串,然后复制行,r,formatting,match,data-management,R,Formatting,Match,Data Management,我有一个多步骤的问题。第一步:将一个字符串(df1)中的文本从一列匹配到另一个列范围(df2)。没有列匹配的顺序,匹配可能发生在范围内的任何位置。找到匹配项后,将df2行匹配项复制到df1中。最后,对整个列重复此操作 df1= structure(list(Assay = c("ATG_AR_trans_up","NVS_PXR_cis","BSK_VCAM1_up"), p.value = c(0.01,0.05,0.0001)), .Names = c("Assay", "p.value")

我有一个多步骤的问题。第一步:将一个字符串(df1)中的文本从一列匹配到另一个列范围(df2)。没有列匹配的顺序,匹配可能发生在范围内的任何位置。找到匹配项后,将df2行匹配项复制到df1中。最后,对整个列重复此操作

df1= structure(list(Assay = c("ATG_AR_trans_up","NVS_PXR_cis","BSK_VCAM1_up"), p.value = c(0.01,0.05,0.0001)), .Names = c("Assay", "p.value"),row.names = c(NA, 3L), class = "data.frame") 

df1
Assay               p.value
ATG_AR_trans_up       0.01
NVS_hPXR              0.065
BSK_VCAM1_up          0.001

df2=structure(list(GeneID = c("AR", "VACM1", "TR", "ER", "PXR"), Assay1= c("ATG_ARE_cis", "BSK_hEDG_VCAM1", "NVS_TR_tran", "ATG_ER_UP", "NVS_PXRE_UP"), Assay2= c("ATG_AR_trans_up", "BSK_BE3K_VCAM1", "NA", "ATG_ERE_cis", "ATG_PXRE_cis"), Assay3= c("NVS_AR_trans", "BSK_VCAM1_UP", "NA", "NVS_ERa_CIS", "NVS_PXR_cis"), Assay4= c("Tox21_AR_ARE","NA", "NA", "Tox21_ERaERb_lig", "NA")),  .Names = c("GeneID", "Assay1", "Assay2", "Assay3", "Assay4"),row.names = c(NA, 5L), class = "data.frame")

df2  
    GeneID             Assay1            Assay 2           Assay3
    AR                 ATG_ARE_cis       NVS_hAR          ATG_AR_trans_up
    VACM1              BSK_hEGF_CAM1     BSK_VCAM1_up      BSK_VCAM1_down
    TR                 NVS_TR_tran       NA                  NA
    ER                 ATG_ER_UP         ATG_ERE_cis     NVS_ERa_CIS     
    PXR                ATG_PXR_down      ATG_PXRE_cis      NVS_hPXR
本质上成为

df
Assay           p.value   GeneID    Assay1       Assay2      Assay3
ATG_AR_trans_up  0.01      AR      ATG_ARE_cis  NVS_hAR      ATG_AR_trans_up
NVS_hPXR         0.065    PXR    ATG_PXR_down   ATG_PXRE_cis NVS_hPXR
BSK_VCAM1_up     0.001    VCAM1  BSK_hEGF_CAM1  BSK_VCAM1_up BSK_VCAM1_down
为简洁起见,我大幅缩短了df,但一次匹配大约需要88次分析和4000多行(大约有30行)。因此,我最初的直觉是循环,但有人告诉我,
grep
可能是一个有用的包(尽管它不适用于R3.2.2)。任何帮助都将不胜感激。

在用户澄清后编辑:

我刚刚创建了一个三重for循环来检查你的值。基本上,它所做的是寻找一个匹配。它通过循环遍历所有列和该列中的所有值来实现这一点

然而,我的代码还不完美(也是R的初学者),我只是想发布它,以便我们可以一起解决一些问题:)

所以我首先将数据转换为data.frame。之后,我创建了一个空的输出,然后根据找到的匹配项填充该输出

此方法的改进在于,使用此解决方案,函数append还将追加列名,这将导致多个无用的列名

df3 <- as.data.frame(df1)
df4 <- as.data.frame(df2)
output <- data.frame()



for(j in 1:nrow(df3)) {
    match <- FALSE
    for(i in 2:(ncol(df4))) {
        for(p in 1:nrow(df4)) {
            if((df3[j, 1] == df4[p, i]) && (match == FALSE)) {
                output <- append(output, c(df3[j, ], df4[j, ]))
                match <- TRUE
            }
        }
    }
}

df3由于您是R新手,我认为您是对的,最直观的方法是使用for循环。这不是最简洁或最有效的方法,但应该清楚发生了什么

# Creating example data
df1 <- as.data.frame(matrix(data=c("aa", "bb", "ee", .9, .5, .7), nrow=3))
names(df1) <- c("assay", "p")

df2 <- as.data.frame(matrix(data=c("G1", "G2", "aa", "dd", "bb", "ee", "cc", "ff"), nrow=2))
names(df2) <- c("GeneID", "assay1", "assay2", "assay3")

# Building a dataframe to store output

df3 <- as.data.frame(matrix(data=NA, nrow=dim(df1)[1], ncol=dim(df2)[2]))
names(df3) <- names(df2)

# Populating dataframe with output
for(i in 1:dim(df1)[1]){
  index <- which(df2==as.character(df1$assay[i]), arr.ind = TRUE)[1]
  for(j in 1:dim(df3)[2]){
  df3[i,j] <- as.character(df2[index,j])
  }
}

df <- cbind(df1, df3)
#创建示例数据

df1这可以通过整形轻松完成。我把所有的分析都放进所有的瓶盖里,因为那会把匹配搞砸

library(dplyr)
library(tidyr)
library(stringi)

df2_ID = df %>% mutate(new_ID = 1:n() )

result = 
  df2_ID %>%
  select(new_ID, Assay1:Assay85) %>%
  gather(assay_number, Assay, Assay1:Assay85) %>%
  mutate(Assay = 
           Assay %>% 
           iconv(to = "ASCII") %>%
           stri_trans_toupper) %>%
  inner_join(df1 %>%
               mutate(Assay = 
                        Assay %>% 
                        iconv(to = "ASCII") %>%
                        stri_trans_toupper)) %>%
  inner_join(df2_ID)

由于OP对
grep
解决方案感兴趣,另一种方法是

asDF2 <- apply(df2, 1, function(r) do.call(paste, as.list(r)))

do.call(rbind, lapply(1:nrow(df1), 
                  function(i){
                    matchIX <- grepl(df1$Assay[i], asDF2, ignore.case=T)
                    if(any(matchIX))
                      cbind(df1[i, ], df2[matchIX, ])
                  }))
请注意,上述变体可以将
df2
中的多行匹配到
df1

注意 为了测试,我将新行添加到原始数据帧中,如下所示

df1 <- rbind(df1, data.frame(Assay="NoMatch", p.value=.2))
df2 <- rbind(df2,
         data.frame(GeneID="My", Assay1="NVS_PXR_cis", Assay2="NA", Assay3="NA", Assay4="NA"))

df1假设没有与df1中的条目对应的任何重复条目。以下是您问题的解决方案:

assay <-as.matrix(df1[,1])
m1 <- as.numeric(sapply(assay, function(x){grep(x,df2[,2], ignore.case = T)}, simplify = FALSE))
m2 <- as.numeric(sapply(assay, function(x){grep(x,df2[,3], ignore.case = T)}, simplify = FALSE))
m3 <- as.numeric(sapply(assay, function(x){grep(x,df2[,4], ignore.case = T)}, simplify = FALSE))
m4 <- as.numeric(sapply(assay, function(x){grep(x,df2[,5], ignore.case = T)}, simplify = FALSE))

m1[is.na(m1)] <- 0
m2[is.na(m2)] <- 0
m3[is.na(m3)] <- 0
m4[is.na(m4)] <- 0

m0 <- (m1+m2+m3+m4)
df <- NULL
for(i in 1:nrow(df1){
  df3 = cbind(df1[i,],df2[m0[i],])
  df = rbind(df,df3)
}


您的示例太小。尝试添加更多匹配项以显示所需的输出。确定。我试试看。如果可以接受编辑,请告诉我您可以编辑问题。您还应该使用
dput
存放示例,这样人们就不必手动复制dfs。我添加了数据帧。希望这能让它更容易理解…虽然我觉得我让它更混乱。谢谢,但我也需要添加匹配的条件。可能是因为我问问题的方式不好。我尝试添加数据帧以使其更容易。这个问题的框架是否仍然很糟糕?“我想是我把事情弄得更糟了。”艾斐特,我认为你的编辑很清楚;这绝对没有让事情变得更糟。谢谢你添加的信息!问题中不清楚的部分是,行找到匹配项的条件是什么。在前两个输出行中,我注意到“Assay”和“Assay3”中有一个匹配项。但在您的第三排,我注意到“Assay”和“Assay 2”匹配。那么,它是否应该在第二个数据帧的三个“分析”中找到一个匹配项呢?是的。没有特定的列匹配顺序。我只需要在任何分析列中找到一个匹配项(实际上有88个,但为了便于示例,我认为3/4就足够了)。这是你应该提到的,哈哈。我在考虑做一个for循环,但是如果你有88列,那么做88个if-else语句将是一种非常糟糕的编码方式。谢谢!抱歉,我花了一点时间运行代码,但我得到了!!等待在我看来,它似乎在工作,但并没有找到所有匹配项。有什么想法可能会出错吗?这取决于数据帧的完整结构。您可以尝试将for循环中的which语句替换为
which((as.character(df2)==as.character(df1$assay[i]),arr.ind=TRUE)[1]
我收到一个语法错误,无法解决它:“error:unexpected”,“in:”for(i in 1:dim(df1)[1]){索引太棒了。我如何/在哪里保存它?我已经编辑过,所以答案保存在一个名为result的数据框中。谢谢!不过仍然有问题。我只在结果中获得了46个变量中的19个。此外,我还收到了一条警告消息:“警告消息:度量变量之间的属性不相同;它们将被删除”有什么想法吗?这里发生的事情(如我的回答)是,应该匹配的元素有一些微妙的地方导致它们不匹配。可能是大小写问题、不知道存在的前导或尾随空格,或者不同的数据类型(例如,有些存储为字符,另一些存储为因子)。但由于某些原因,您认为应该匹配的单元格实际上并不匹配。要检查这一点,请找到一个未正确提取的匹配项,并检查df1和df2中的相关条目是否与前面的一致。其他可能导致问题的内容是“不可见的”字符。转换为ascii有时会有帮助。你太棒了。它工作了50%。我基本上必须为两组不同的数据帧运行这段代码两次。第一组最终工作了,但当我运行第二组时,我得到了错误:“data.frame中的错误(…,check.names=FALSE):参数意味着不同的行数:1,0 7停止(gettextf(“参数表示不同的行数:%s”),粘贴(唯一(nrows),collapse=“,”),domain=NA)6数据帧(…,check.names=FALSE)5 cbind(deparse.level,…)4 cbind(p.MDRatT[i,],AmigoDEV[grepl(p.MDRatT$Assay[i],data.frame(t(AmigoDEV,stringsafactors=F),ignore.case=t),]))3乐趣(X[[i],…)2 lappy(1)nrow(p.MDRatT),function(i)cbind(p.MDRatT[i,],AmigoDEV[grepl(p.MDRatT$Assay[i],data.frame(t(AmigoDEV),stringsAsFactors=F),ignor
assay <-as.matrix(df1[,1])
m1 <- as.numeric(sapply(assay, function(x){grep(x,df2[,2], ignore.case = T)}, simplify = FALSE))
m2 <- as.numeric(sapply(assay, function(x){grep(x,df2[,3], ignore.case = T)}, simplify = FALSE))
m3 <- as.numeric(sapply(assay, function(x){grep(x,df2[,4], ignore.case = T)}, simplify = FALSE))
m4 <- as.numeric(sapply(assay, function(x){grep(x,df2[,5], ignore.case = T)}, simplify = FALSE))

m1[is.na(m1)] <- 0
m2[is.na(m2)] <- 0
m3[is.na(m3)] <- 0
m4[is.na(m4)] <- 0

m0 <- (m1+m2+m3+m4)
df <- NULL
for(i in 1:nrow(df1){
  df3 = cbind(df1[i,],df2[m0[i],])
  df = rbind(df,df3)
}
assay <-as.matrix(df1[,1])

# Storing Assay column in a list
m <- vector('list',ncol(df2[, 2:ncol(df2)]))
for(i in 1:length(m)){
  m[[i]] <- as.numeric(sapply(assay, function(x){grep(x,df2[,(i+1)], ignore.case = T)}, simplify = FALSE))

}
# Getting row subscript for df2
m1 <- as.data.frame(m)
m1[is.na(m1)] <- 0
m2 <- rowSums(m1)

df <- NULL
for(i in 1:nrow(df1)){
  df3 = cbind(df1[i,],df2[m2[i],])
  df = rbind(df,df3)
}