web-dev-qa-db-ja.com

行ごとにJava RDDを繰り返す

文字列のRDDを繰り返し処理し、各文字列に対して「何かを実行」したいと思います。出力はdouble[][]である必要があります。これは、forループの例です。 Java RDDにforeach関数を使用する必要があることを理解しています。ただし、構文を理解する方法がわかりません。ドキュメントは特に役に立ちません。I Java 8はありません。

これは、通常のforループを使用できる場合に実行したい例です。

public class PCA {

    public static void main(String[] args) {
        SparkConf conf = new SparkConf().setAppName("PCA Example");
        SparkContext sc = new SparkContext(conf);

        RDD<String> data = sc.textFile("my/directory/my/dataset.txt", 0);

        // here is the "type" of code I would like to execute
        // 30 because I have 30 variables
        double[][] vals = new double[data.count()][30];

        double[] temp;
        for (int i = 0; i < data.count(); i++) {
            temp = splitStringtoDoubles(data[i]);
            vals[i] = temp;
        }
    }

    private static double[] splitStringtoDoubles(String s) {
        String[] splitVals = s.split("\\t");
        Double[] vals = new Double[splitVals.length];
        for (int i = 0; i < splitVals.length; i++) {
            vals[i] = Double.parseDouble(splitVals[i]);
        }
    }

}

foreachにはvoidの戻り値の型を持つ関数が必要なようです。それをどのように扱うかわからない。これが私がこれまでに試みたことです(明らかに構文が間違っています):

    double[][] matrix = new double[data.count()][30];
    foreach(String s : data) {
        String[] splitvals = s.split("\\t");
        double[] vals = Double.parseDouble(splitvals);
        matrix[s] = vals; 
    }
9
Katya Handler

mattinbitsコメントで述べたように、値を返したいので、mapではなくforeachが必要です。 mapが行うことは、基本的にデータを変換することです。RDDの各行に対して操作を実行し、各行に1つの値を返します。必要なことは次のように達成できます。

import org.Apache.spark.api.Java.function.Function;

...

SparkConf conf = new SparkConf().setAppName("PCA Example");
SparkContext sc = new SparkContext(conf);

JavaRDD<String> data = sc.textFile("clean-sl-mix-with-labels.txt",0).toJavaRDD();
JavaRDD<double[]> whatYouWantRdd = data.map(new Function<String, double[]>() {
    @Override
    public double[] call(String row) throws Exception {
        return splitStringtoDoubles(row);
    }

    private double[] splitStringtoDoubles(String s) {
        String[] splitVals = s.split("\\t");
        Double[] vals = new Double[splitVals.length];
        for(int i=0; i < splitVals.length; i++) {
            vals[i] = Double.parseDouble(splitVals[i]);
        }
        return vals;
    }
});

List<double[]> whatYouWant = whatYouWantRdd.collect();

Sparkがどのように機能するかを理解するために、RDDでアクションまたは変換を実行します。たとえば、ここではmap関数を使用してRDDを変換しています。これを作成する必要があります。今度は匿名で機能しますorg.Apache.spark.api.Java.function.Functionこれにより、メソッドcallをオーバーライドする必要があります。このメソッドでは、RDDの行を受け取り、値を返します。

4
Balduz

Java vs Scala API for Sparkの冗長性を比較するのが興味深いという理由だけで、ここにScalaバージョン:

import org.Apache.spark.{SparkContext, SparkConf}

class example extends App {
  val conf = new SparkConf().setMaster("local").setAppName("Spark example")
  val sc = new SparkContext(conf)

  val inputData = List(
    "1.2\t2.7\t3.8",
    "4.3\t5.1\t6.3"
  )

  val inputRDD = sc.parallelize(inputData)
  val arrayOfDoubleRDD = inputRDD.map(_.split("\t").map(_.toDouble))
}
4
mattinbits