2017-10-18 15 views
0

Je suis assez nouveau pour Scala et Spark, et j'avais quelques questions sur l'affichage des résultats dans le fichier de sortie.Afficher la sortie sous un certain format

J'ai une carte dans laquelle chaque clé est associée à une liste de la liste (Map[Int, List<Double>]), tels que:

(2, List(x1,x2,x3), List(y1,y2,y3), ...). 

Je suis censé afficher pour chaque touche les valeurs dans les listes de listes, tels que:

2  x1,x2,x3 
2  y1,y2,y3 
1  z1,z2,z3 

et ainsi de suite. Lorsque j'utilise la fonction saveAsTextFile, cela ne me donne pas ce que je veux dans la sortie. Est-ce que quelqu'un sait comment je peux le faire?

EDIT: Ce est l'une de ma fonction:

def PrintCluster(vectorsByKey : Map[Int, List[Double]], vectCentroidPairs : Map[Int, Int]) : Map[Int, List[Double]] = { 

    var vectorsByCentroid: Map[Int, List[Double]] = Map() 
    val SortedCentroid = vectCentroidPairs.groupBy(_._2).mapValues(x => x.map(_._1).toList).toSeq.sortBy(_._1).toMap 
    SortedCentroid.foreach { case (centroid, vect) => 
     var nbVectors = vect.length 

     for (i <- 0 to nbVectors - 1) { 
     var vectValues = vectorsByKey(vect(i)) 
     println(centroid + " " + vectValues) 
     vectorsByCentroid += (centroid -> (vectValues)) 
     } 
    } 
    return vectorsByCentroid 
    } 

Je sais qu'il est mal, parce que je ne peux affecter une clé unique pour un groupe de valeurs. C'est pourquoi il ne me renvoie que la première liste pour chaque touche de la carte. Je pensais que pour utiliser la fonction saveAsTextFile, j'ai dû nécessairement utiliser une structure de carte, mais je ne sais pas vraiment.

+0

Qu'est-ce que 'saveAsTextFile' vous donner et comment fonctionne-t-il différent de ce que vous voulez? En outre, il ne semble pas que vous ayez une liste de listes mais des listes normales ('Map [Int, List [Double]]')? – Shaido

+0

Vous pourriez vouloir montrer votre code Scala. Également, essayez d'écrire un jeu de données en utilisant le format CSV mais réglez le délimiteur sur un onglet –

+0

@Shaido La sortie que j'ai est logique, je veux dire ... Puisque je ne peux avoir qu'une seule clé pour une valeur (format carte), seulement La première valeur est imprimée. C'est ce que j'ai: (3, Liste (-2.7, 6.1, -2.8)), (2, Liste (-2.7, 7.1, -2.8)). – Sol

Répondre

0

L'utilisation d'un Map[Int, List[List[Double]]] et simplement l'imprimer dans le format voulu est simple, il peut être fait en premier convertir en une liste, puis en appliquant flatMap. À l'aide des données fournies dans un commentaire:

val map: Map[Int, List[List[Double]]] = Map(
    2 -> List(List(-4.4, -2.0, 1.5), List(-3.3, -5.4, 3.9), List(-5.8, -3.3, 2.3), List(-5.2, -4.0, 2.8)), 
    1 -> List(List(7.3, 1.0, -2.0), List(9.8, 0.4, -1.0), List(7.5, 0.3, -3.0), List(6.1, -0.5, -0.6), List(7.8, 2.2, -0.7), List(6.6, 1.4, -1.1), List(8.1, -0.0, 2.7)), 
    3 -> List(List(-3.0, 4.0, 1.4), List(-4.0, 3.9, 0.8), List(-1.4, 4.3, -0.5), List(-1.6, 5.2, 1.0)) 
) 

val list = map.toList.flatMap(t => t._2.map((t._1, _))) 
val result = for (t <- list) yield t._1 + "\t" + t._2.mkString(",") 

// Saving the result to file 
import java.io._ 
val pw = new PrintWriter(new File("fileName.txt")) 
result.foreach{ line => pw.println(line)} 
pw.close 

imprimera:

2 -4.4,-2.0,1.5 
2 -3.3,-5.4,3.9 
2 -5.8,-3.3,2.3 
2 -5.2,-4.0,2.8 
1 7.3,1.0,-2.0 
1 9.8,0.4,-1.0 
1 7.5,0.3,-3.0 
1 6.1,-0.5,-0.6 
1 7.8,2.2,-0.7 
1 6.6,1.4,-1.1 
1 8.1,-0.0,2.7 
3 -3.0,4.0,1.4 
3 -4.0,3.9,0.8 
3 -1.4,4.3,-0.5 
3 -1.6,5.2,1.0 
+0

Cela fonctionne! Mais n'affiche rien comme sortie ... Est-ce normal? – Sol

+0

@ Sol Il devrait imprimer les lignes avec 'println()'. Code inclus donc vous obtenez également un 'List [String]' comme résultat. – Shaido

+0

Je veux dire ... Comment puis-je mettre cet algorithme dans le fichier saveAsTextFile? – Sol

1

créer échantillon RDD selon vos données d'entrée

val rdd: RDD[Map[Int, List[List[Double]]]] = spark.sparkContext.parallelize(
    Seq(Map(
    2 -> List(List(-4.4, -2.0, 1.5), List(-3.3, -5.4, 3.9), List(-5.8, -3.3, 2.3), List(-5.2, -4.0, 2.8)), 
    1 -> List(List(7.3, 1.0, -2.0), List(9.8, 0.4, -1.0), List(7.5, 0.3, -3.0), List(6.1, -0.5, -0.6), List(7.8, 2.2, -0.7), List(6.6, 1.4, -1.1), List(8.1, -0.0, 2.7)), 
    3 -> List(List(-3.0, 4.0, 1.4), List(-4.0, 3.9, 0.8), List(-1.4, 4.3, -0.5), List(-1.6, 5.2, 1.0))) 
) 
) 

Transform RDD[Map[Int, List[List[Double]]]] à RDD[(Int, String)]

val result: RDD[(Int, String)] = rdd.flatMap(i => { 
    i.map { 
    case (x, y) => y.map(list => (x, list.mkString(" "))) 
    } 
}).flatMap(z => z) 

result.foreach(println) 

result.saveAsTextFile("location") 
+0

Pas vraiment. En fait, j'ai une fonction (vide) qui imprime pour chaque clé la valeur (x, y, z). Donc je sais que ça fonctionne. Le problème est que je ne sais pas comment retourner un format correct pour afficher le résultat que je veux. Si je renvoie un résultat, il ne peut pas s'agir d'une carte car une carte a une clé unique et j'ai plusieurs valeurs partageant la même clé. C'est pourquoi ma sortie ne me donne pas la bonne chose. Ce sont mes dernières lignes: 'val mapResult = PrintCluster (vectKeys, vectCentroidPair) sc.parallelize (mapResult.toSeq, 2) .saveAsTextFile ("résultat")' – Sol

+0

Pouvez-vous vérifier la modification. Sinon, essayez d'ajouter l'entrée d'échantillon rdd. – mrsrinivas

+0

Désolé, je suis un peu confus au sujet de mon bon code. J'ai édité mon post. En fait, J'ai deux cartes vraiment importantes: La première: vectorsByKey, correspond à une clé aléatoire pour chaque vecteur, comme: 'Map (25, liste (x, y, z))'. Le second: vectCentroidPairs, fait correspondre chaque vecteur sous sa valeur de clé aléatoire avec le centroïde correspondant (algorithme K-mean). J'ai quelque chose comme ça: 'Map (1, List (5, 37, 25, 78, 70, 33, 53, 41, 32, 64, 27)).' Ce que je dois faire est de récupérer les vraies valeurs sous la clé (donc les listes) et l'afficher pour chaque centroïde correspondant (1, 2 ou 3). – Sol