2017-04-26 1 views
2

Array[Option[Long]]을 선형 보간하려고합니다. 주어진 예를 들어 :스칼라에서 배열 보간

val example1 = Array(Some(20l), None, Some(60l)) 
val example2 = Array(Some(20l), None, None, Some(80l)) 
val example3 = Array(Some(20l), None, None, Some(80l), Some(90l), Some(100l)) 
val example4 = Array(Some(20l), None, None, Some(80l), None, Some(82l)) 

내가 기대 해요 : 컬렉션 (예를 들어, example4)의 요소 사이의 관계가

val example1Interpolated = Array(20l, 40l, 60l) 
val example2Interpolated = Array(20l, 40l, 60l, 80l) 
val example3Interpolated = Array(20l, 40l, 60l, 80l, 90l, 100l) 
val example4Interpolated = Array(20l, 40l, 60l, 80l, 81l, 82l) 

없습니다. 그러나 값은 단조롭게 증가합니다.

def interpolate(input_): 
    nans = np.isnan(input_) 
    get_index = lambda z: z.nonzero()[0] 
    input_[nans] = np.interp(get_index(nans), get_index(~nans), input_[~nans]) 
    return input_ 

을 위해 :

interpolate(np.array([20, np.nan, 60])) 
interpolate(np.array([20, np.nan, np.nan, 80])) 
interpolate(np.array([20, np.nan, np.nan, 80, np.nan, 82])) 

수율 :

array([ 20., 40., 60.]) 
array([ 20., 40., 60., 80.]) 
array([ 20., 40., 60., 80., 81., 82.]) 
+2

지금까지 해보신 것은 무엇입니까? 어디에서 차단 되었습니까? 구체적인 문제가 뭐니? – sjrd

+0

@sjrd는 선택적 값을 가진 콜렉션에서 주어진 기능적인 방법을 찾고 있습니다. 일부 패키지에 누군가가 알고있는 것 또는 내가 누락 된 것을 구현했는지 궁금합니다. –

+3

@AmirZiai 질문에 필요한 정확한 요구 사항을 추가해야합니다. –

답변

3

이 기능은 한 Some(_)입니다 목록에서 적어도 하나 개의 원소가 존재하는 한,이 선행 또는 None 후행하는 경우에도 작동합니다. Integral 유형에도 일반적입니다. (당신이 원하는 경우 Fractional 유형에 걸쳐이 일반적인 만들 수 있습니다.)

def interpolate[T](list: Iterable[Option[T]])(implicit num: Integral[T]) = { 
    import num._ 
    val prevs = list.zipWithIndex.scanLeft(Option.empty[(T, Int)]) { 
    case (prev, (cur, i)) => cur.map((_, i)).orElse(prev) 
    } 
    val nexts = list.zipWithIndex.scanRight(Option.empty[(T, Int)]) { 
    case ((cur, i), next) => cur.map((_, i)).orElse(next) 
    } 
    prevs.tail.zip(nexts).zipWithIndex.map { 
    case ((Some((prev, i)), Some((next, j))), k) => 
     if (i == j) prev else prev + (next - prev) * fromInt(k - i)/fromInt(j - i) 
    case ((Some((prev, _)), _), _) => prev 
    case ((_, Some((next, _))), _) => next 
    } 
} 

이것은 prevs을 축적는 동일한되는, 가장 최근의 Some(_) 왼쪽에 색인 및 nexts를 추적하는 권리. 그런 다음 병렬로 prevsnexts을 반복하여 왼쪽, 오른쪽 및 인덱스를 기반으로 보간 값을 생성합니다. 왼쪽 또는 오른쪽이없는 경우 다른 쪽에서 채우십시오.

2

내가 아니다 나는 다음의 스칼라 해당 찾고 있어요 파이썬에 익숙한 사람들을 위해

numpy에 익숙하지만이 모든 사례를 처리한다고 생각합니다. 목록의 첫 번째 요소와 마지막 요소가 정의 된 것으로 가정합니다 (그렇지 않은 경우 fillNones 함수를 다시 작업해야 함).

def interpolate(list: List[Option[Long]]) = { 

    // Creates a new list that will be used to replace a sequence of Nones 
    def fillNones(noneCount: Int, min: Long, max: Long): List[Long] = { 
    val stepSize = (max - min)/(noneCount + 1) 
    (1 to noneCount).toList.map(i => i * stepSize + min) 
    } 

    // We will recursively traverse the list 
    def recursive(done: List[Long], todo: List[Option[Long]]): List[Long] = { 
    todo match { 

     // If todo is empty, we are done 
     case Nil => done 

     // If the head of todo is Some(Long), then add it to the list of things that are done and move on 
     case Some(l) :: tail => recursive(done :+ l, tail) 

     // If the head wasn't Some(Long), then we have to figure out how many Nones are in a row, and replace them 
     case todo => 

     // Find out how many Nones are in a row 
     val noneCount = todo.takeWhile(_.isEmpty).length 

     // Split the todo so we can get what is remaining 
     val remaining = todo.splitAt(noneCount)._2 

     // Create a new list to replace the sequence of Nones 
     val filled = fillNones(noneCount, done.last, remaining.head.get) 

     // Add our new filled list to done, and continue on 
     recursive(done ++ filled, remaining) 
    } 
    } 

    recursive(List.empty, list) 
} 

테스트 :

val example1 = List(Some(20l), None, Some(60l)) 
println(interpolate(example1)) 
// Prints: List(20, 40, 60)  

val example2 = List(Some(20l), None, None, Some(80l)) 
println(interpolate(example2)) 
// Prints: List(20, 40, 60, 80) 

val example3 = List(Some(20l), None, None, Some(80l), Some(90l), Some(100l)) 
println(interpolate(example3)) 
// Prints: List(20, 40, 60, 80, 90, 100) 

val example4 = List(Some(20l), None, None, Some(80l), None, Some(82l)) 
println(interpolate(example4)) 
// Prints: List(20, 40, 60, 80, 81, 82)