2016-04-27 3 views
1

У меня есть файл с 10 столбцами. Какой самый элегантный способ извлечь только первые 3 столбца или конкретные столбцы?Извлечь только определенные столбцы в Java Spark

Например, это как мой файл выглядит следующим образом:

john,smith,84,male,kansas 
john,doe,48,male,california 
tim,jones,22,male,delaware 

И я хочу, чтобы извлечь в этом:

[john, smith, kansas] 
[john, doe, california] 
[tim, jones, delaware] 

Что у меня есть, но это не специально выбрал столбцы, которые я хочу:

JavaRDD<String> peopleRDD = sc.textFile(DATA_FILE); 
peopleRDD.cache().map(lines -> Arrays.asList(lines.split(","))) 
       .forEach(person -> LOG.info(person)); 

Я прочитал followingtwo Stack но я все еще не могу решить, как это сделать.

EDIT: я в конечном итоге делает следующее:

JavaRDD<String> peopleRDD = sc.textFile(DATA_FILE); 
    peopleRDD.cache().map(lines -> Arrays.asList(new String[]{lines.split(",")[0], 
                 lines.split(",")[1], 
                 lines.split(",")[3]} 
        .forEach(person -> LOG.info(person)); 

Не самое элегантное решение, но если у вас есть лучший способ, пожалуйста, напишите здесь. Благодарю.

+0

Лично я бы использовал SparkSQL + Dataframes. К сожалению, я знаю только реализацию Python, но здесь есть [документация для этого] (http://spark.apache.org/docs/latest/sql-programming-guide.html#inferring-the-schema- using-reflection) –

ответ

1

EDIT: Извиняюсь, я просто понял, что вы просите Java-решение, но я использовал Scala. Только 3-е из моих предложений имеет эквивалент в Java (добавлено в нижней части ответа) ... Искра на самом деле намного приятнее в Scala :-)

Один из способов - выполнить split, затем совпадение шаблонов на результат, чтобы выбрать столбцы, которые вы хотите:

peopleRDD.cache().map(_.split(",") match { case Array(a,b,_,_,e) => List(a,b,e) }) 

Другой (в зависимости от того, какие комбинации элементов, которые вы хотите) заключается в использовании take и drop, используя val, чтобы избежать расщепления повторно.

peopleRDD.cache().map{ line => 
    val parts = line.split(",") 
    parts.take(2) ++ parts.drop(4) 
} 

(Вы можете добавить toList после split если вы хотите List, а не Array для каждого конечного элемента в РДУ)

В действительности же подход может быть использован для упрощения оригинального решения , например:

peopleRDD.cache().map{ line => 
    val parts = line.split(",") 
    List(parts[0], parts[1], parts[4]) 
} 

В Java8, вы, вероятно, можете сделать эквивалент, который является небольшим улучшением, как мы не вызывать split разы - что-то Лик e:

peopleRDD.cache().map(line -> { 
    Array<String> parts = line.split(","); 
    Arrays.asList(new String[]{parts[0], parts[1], parts[4]}); 
}) 
+0

В итоге я сделал что-то похожее на то, что вы упомянули в своем правлении о Java8 с lambdas. – BlueChips23

Смежные вопросы