2016-12-13 5 views
1

참고 :이 질문의 '데이터 프레임'은 실제로 행렬입니다. 대답은 여전히 ​​의미가 있도록 나는 표현을 떠난, 그리고 솔루션은 모두 dataframes 및 행렬에서 작동하기 때문에데이터 프레임에서 숫자 목록에 가까운 값 검색

나는 대중과 해당 강도의 목록이 포함 된 dataframe 있습니다

> df <- cbind(c(3.43534, 5.324, 9.322, 123.234), c(31, 4214, 112, 44)) 
> colnames(df) <- c("Mass", "I") 
> df 
      Mass I 
[1,] 3.43534 31 
[2,] 5.32400 4214 
[3,] 9.32200 112 
[4,] 123.23400 44 

I을 내가 처음 안양에서 화합물을 식별 할 수 있도록하려는

> compounds <- cbind(c(3.39, 102.93, 9.310, 144.00), c("A", "B", "C", "D")) 
> colnames(compounds) <- c("Mass", "Compound") 
> compounds 
    Mass  Compound 
[1,] "3.39" "A"  
[2,] "102.93" "B"  
[3,] "9.31" "C"  
[4,] "144" "D" 

: 대중의 목록과 해당 화합물의 이름이 포함 된 다른 dataframe 있습니다. 질량이 정확하다면 이것은 매우 간단 할 것입니다. 그러나 실험적 오류로 인해 첫 번째 데이터 프레임의 질량은 '화합물'데이터 프레임의 질량과 숫자가 동일하지 않습니다.

화합물 데이터 프레임을 검색하여 첫 번째 df에서 1에 가까운 행을 모두 찾는 방법은 무엇입니까? 저를 줄 것 0.2의 허용 오차를 허용 예를 들어

 Mass  Compound 
[1,] "3.39" "A"  
[2,] "9.31" "C"  

실제 수명 데이터 행의 수천, 그래서 불행하게도 루프가 너무 느린 것입니다.

tol <- 0.2 
compounds[which(do.call(pmin,as.data.frame(abs(outer(compounds$Mass, df$Mass, "-")))) < tol),] 
## Mass Compound 
##1 3.39  A 
##3 9.31  C 

참고 :

+1

들은 행렬이다 데이터 프레임이 아닙니다. –

+0

죄송합니다. 올바른 답변입니다. 나는이 실수를했다. 왜냐하면 내가 사용하고있는 전체 데이터 세트는 data.frame이지만, aichao의 솔루션이 여전히 작동하기 때문이다. 지금 문구를 바꿀 것입니다. –

답변

1

이 그것을해야

  1. 연산자를 사용 outer '-'각 compounds$Massdf$Mass의 차이 행렬을 계산.
  2. abs을 가져 가서 거리 매트릭스를 얻으십시오.
  3. 사용 do.call(pmin,as.data.frame(...))은 (즉, 각 compounds$Mass)
  4. 서브 세트 compounds는 거리가 허용 오차보다 작은 which를 위해 해당 행을 사용하여 각 행의 최소 거리를 계산합니다.

편집 대답 사실

, 우리는 df의 모든 행의 tol 내에있는 compounds, 우리는 실제로 최소 거리를 계산 할 필요가 없습니다 원하기 때문에; 그러므로 :

compounds[unique(which(abs(outer(compounds$Mass, df$Mass, "-")) < tol, arr.ind=TRUE)[,1]),] 
## Mass Compound 
##1 3.39  A 
##3 9.31  C 

조금 더 빠를 것입니다.

데이터 : 여기

df <- structure(list(Mass = c(3.43534, 5.324, 9.322, 123.234), I = c(31, 
4214, 112, 44)), .Names = c("Mass", "I"), row.names = c(NA, -4L 
), class = "data.frame") 
##  Mass I 
##1 3.43534 31 
##2 5.32400 4214 
##3 9.32200 112 
##4 123.23400 44 

compounds <- structure(list(Mass = c(3.39, 102.93, 9.31), Compound = structure(1:3, .Label = c("A", 
"B", "C"), class = "factor")), .Names = c("Mass", "Compound"), row.names = c(NA, 
-3L), class = "data.frame") 
## Mass Compound 
##1 3.39  A 
##2 102.93  B 
##3 9.31  C 
##4 144.00  D 
+0

매우 흥미로운 해결책이지만, 여전히 do.call로 인해 루프를 수행합니다. – Gopala

+0

둘 다 감사합니다! 각 솔루션을 테스트하여 풀 사이즈 데이터 세트에서 어떤 솔루션이 더 빠르게 작동하는지 확인하십시오. –

+0

@Gopala : 사실, do.call은 목록 (즉, 거리 행렬의 열)에 대해 병렬 min 인'pmin '을 호출하기 때문에 실제로 그렇게 생각하지 않습니다. 이것이 우리가 컬럼의리스트를주는'as.data.frame'을 사용하여 변환하는 이유입니다. – aichao

1

내가 원하는 조건에 기초하여 필터링 한 다음 두 개의 데이터 세트에 가입하는 방법에 관해서는 마련 할 하나의 해결책이다

df <- data.frame(Mass = c(3.43534, 5.324, 9.322, 123.234), 
       I = c(31, 4214, 112, 44)) 
compounds <- data.frame(Mass = c(3.39, 102.93, 9.310, 144.00), 
         Compound = c("A", "B", "C", "D"), 
         stringsAsFactors = FALSE) 

df <- expand.grid(df$Mass, 1:nrow(compounds)) 
df <- cbind(Var1 = df$Var1, compounds[df$Var2, ]) 
unique(df[(df$Mass > df$Var1 - 0.2 & df$Mass < df$Var1 + 0.2), 
      c('Mass', 'Compound')]) 
+0

데이터 크기에 따라 너무 많은 메모리를 사용하므로주의하십시오. – Gopala

+0

오류 : 'x'객체가 없습니다. –

+0

죄송합니다. 나는 x에서 df로 이름을 바꾸었지만 그것을 완전히 고치지는 않았다. 자, 편집. – Gopala

관련 문제