Rdd nesnesini kıvılcım içinde veri karesine dönüştürme


139

Nasıl bir RDD ( org.apache.spark.rdd.RDD[org.apache.spark.sql.Row]) bir Dataframe dönüştürebilirsiniz org.apache.spark.sql.DataFrame. Ben kullanarak bir veri çerçevesi rdd dönüştürdü .rdd. İşledikten sonra veri çerçevesinde geri istiyorum. Bunu nasıl yapabilirim ?


içinde bunu başarmak için bir yol Kıvılcım 2.x
mrsrinivas

Yanıtlar:


88

SqlContextbir sayıda createDataFramebir oluşturmak yöntemler DataFrameverilen RDD. Bunlardan birinin bağlamınız için işe yarayacağını hayal ediyorum.

Örneğin:

def createDataFrame(rowRDD: RDD[Row], schema: StructType): DataFrame

Verilen şemayı kullanarak Satır içeren bir RDD'den bir DataFrame oluşturur.


93

Bu kod Scala 2.11 ile Spark 2.x'ten mükemmel çalışıyor

Gerekli sınıfları içe aktarın

import org.apache.spark.sql.{Row, SparkSession}
import org.apache.spark.sql.types.{DoubleType, StringType, StructField, StructType}

SparkSessionNesne Oluşturun ve işte buradaspark

val spark: SparkSession = SparkSession.builder.master("local").getOrCreate
val sc = spark.sparkContext // Just used to create test RDDs

Izin vermek bir var RDDbunu yapmak içinDataFrame

val rdd = sc.parallelize(
  Seq(
    ("first", Array(2.0, 1.0, 2.1, 5.4)),
    ("test", Array(1.5, 0.5, 0.9, 3.7)),
    ("choose", Array(8.0, 2.9, 9.1, 2.5))
  )
)

Yöntem 1

Kullanma SparkSession.createDataFrame(RDD obj).

val dfWithoutSchema = spark.createDataFrame(rdd)

dfWithoutSchema.show()
+------+--------------------+
|    _1|                  _2|
+------+--------------------+
| first|[2.0, 1.0, 2.1, 5.4]|
|  test|[1.5, 0.5, 0.9, 3.7]|
|choose|[8.0, 2.9, 9.1, 2.5]|
+------+--------------------+

Yöntem 2

SparkSession.createDataFrame(RDD obj)Sütun adlarını kullanma ve belirtme.

val dfWithSchema = spark.createDataFrame(rdd).toDF("id", "vals")

dfWithSchema.show()
+------+--------------------+
|    id|                vals|
+------+--------------------+
| first|[2.0, 1.0, 2.1, 5.4]|
|  test|[1.5, 0.5, 0.9, 3.7]|
|choose|[8.0, 2.9, 9.1, 2.5]|
+------+--------------------+

Yöntem 3 (Soruya gerçek cevap)

Bu şekilde girdi rddtüründe olmalıdır RDD[Row].

val rowsRdd: RDD[Row] = sc.parallelize(
  Seq(
    Row("first", 2.0, 7.0),
    Row("second", 3.5, 2.5),
    Row("third", 7.0, 5.9)
  )
)

şemayı oluştur

val schema = new StructType()
  .add(StructField("id", StringType, true))
  .add(StructField("val1", DoubleType, true))
  .add(StructField("val2", DoubleType, true))

Şimdi hem uygulamak rowsRddve schemakarşıcreateDataFrame()

val df = spark.createDataFrame(rowsRdd, schema)

df.show()
+------+----+----+
|    id|val1|val2|
+------+----+----+
| first| 2.0| 7.0|
|second| 3.5| 2.5|
| third| 7.0| 5.9|
+------+----+----+

2
CreateDataFrame'i anlaşılır bir şekilde kullanmanın farklı yollarını gösterdiğiniz için teşekkür ederiz
vatsug

üçüncü yöntem, diğerleri çalışmadığı ve bir hata verdiği için veri tuğlalarına yardımcı olur
Narendra Maru

67

RDD'nize [satır] rdd denildiğinde, şunu kullanabilirsiniz:

val sqlContext = new SQLContext(sc) 
import sqlContext.implicits._
rdd.toDF()

26
Bence RDD [Row] için işe yaramaz. Bir şey mi kaçırıyorum?
Daniel de Paula

4
Spark 2.0 SQLContext, SparkSession ile değiştirildiğinden, ancak sınıf geriye dönük uyumluluk (scaladoc) için kod tabanında tutulur . Kullanıldığında kullanımdan kaldırma uyarısı verilir.
tomaskazemekas

18

Not: Bu cevap ilk olarak buraya gönderildi

Bu cevabı gönderiyorum çünkü diğer cevaplarda bulamadığım mevcut seçenekler hakkında ek bilgi paylaşmak istiyorum


Satır RDD'sinden bir DataFrame oluşturmak için iki ana seçenek vardır:

1) Zaten işaret toDF()ettiği gibi, hangi tarafından ithal edilebilir kullanabilirsiniz import sqlContext.implicits._. Ancak, bu yaklaşım yalnızca aşağıdaki RDD türleri için geçerlidir:

  • RDD[Int]
  • RDD[Long]
  • RDD[String]
  • RDD[T <: scala.Product]

(Kaynak: Scaladoc arasında SQLContext.implicitsnesnenin)

Son imza aslında tuples RDD veya vaka sınıflarının RDD için çalışabileceği anlamına gelir (çünkü tuples ve case sınıfları alt sınıflardır scala.Product).

Yani, bu yaklaşımı bir için kullanmak için bir RDD[Row]ile eşlemelisiniz RDD[T <: scala.Product]. Bu, aşağıdaki kod parçacıklarında olduğu gibi, her satırı özel bir vaka sınıfına veya bir tuple ile eşleştirerek yapılabilir:

val df = rdd.map({ 
  case Row(val1: String, ..., valN: Long) => (val1, ..., valN)
}).toDF("col1_name", ..., "colN_name")

veya

case class MyClass(val1: String, ..., valN: Long = 0L)
val df = rdd.map({ 
  case Row(val1: String, ..., valN: Long) => MyClass(val1, ..., valN)
}).toDF("col1_name", ..., "colN_name")

Bu yaklaşımın ana dezavantajı (bence), sonuçta ortaya çıkan DataFrame'in şemasını, harita sütununda sütun sütun olarak açıkça ayarlamanız gerektiğidir. Belki şemayı önceden bilmiyorsanız, programlı olarak yapılabilir, ancak işler orada biraz dağınık olabilir. Yani, alternatif olarak, başka bir seçenek var:


2) kullanabilirsiniz createDataFrame(rowRDD: RDD[Row], schema: StructType)mevcuttur kabul cevap olduğu gibi SqlContext nesne. Eski bir DataFrame öğesinin RDD'sini dönüştürme örneği:

val rdd = oldDF.rdd
val newDF = oldDF.sqlContext.createDataFrame(rdd, oldDF.schema)

Herhangi bir şema sütununu açıkça ayarlamanıza gerek olmadığını unutmayın. Eski DF'nin StructTypesınıfsal ve kolayca genişletilebilen şemasını tekrar kullanıyoruz . Bununla birlikte, bu yaklaşım bazen mümkün değildir ve bazı durumlarda birinciden daha az verimli olabilir.


Detay için teşekkürlerimport sqlContext.implicits.
javadba

Gelecekte, lütfen birden fazla soruya özdeş cevaplar göndermeyin. Sorular yineleniyorsa, iyi bir yanıt gönderin, ardından diğer soruyu yinelenen olarak kapatmak için oylayın veya işaretleyin. Soru yinelenmiyorsa, yanıtınızı soruya uygun hale getirin. Bkz. İyi bir cevabı nasıl yazarım? .

15

Varsayalım DataFrameve alan verilerinde dönüştürerek bazı değişiklikler yapmak istediğinizi varsayalım RDD[Row].

val aRdd = aDF.map(x=>Row(x.getAs[Long]("id"),x.getAs[List[String]]("role").head))

Geri dönüştürmek için DataFramegelen RDDbiz tanımlamanız gerekir yapı tipini arasında RDD.

Eğer veri tipi yapıldıysa yapıdaki Long gibi olacaktır LongType.

Eğer Stringo zaman StringTypeyapıda.

val aStruct = new StructType(Array(StructField("id",LongType,nullable = true),StructField("role",StringType,nullable = true)))

Şimdi RDD'yi createDataFrame yöntemini kullanarak DataFrame'e dönüştürebilirsiniz .

val aNamedDF = sqlContext.createDataFrame(aRdd,aStruct)

7

Listenizi Spark RDD'ye ve ardından bu Spark RDD'yi Dataframe'e dönüştürmenin basit bir örneği.

Aşağıdaki kodu yürütmek için Spark-shell'ın scala REPL kullandığımı lütfen unutmayın, İşte sc Spark-kabuk dolaylı olarak kullanılabilir bir SparkContext örneğidir. Umarım sorunuzu cevaplar.

scala> val numList = List(1,2,3,4,5)
numList: List[Int] = List(1, 2, 3, 4, 5)

scala> val numRDD = sc.parallelize(numList)
numRDD: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[80] at parallelize at <console>:28

scala> val numDF = numRDD.toDF
numDF: org.apache.spark.sql.DataFrame = [_1: int]

scala> numDF.show
+---+
| _1|
+---+
|  1|
|  2|
|  3|
|  4|
|  5|
+---+

Eğlenceli bir gerçek: Listeniz int (veya Long, String, <: Product) yerine Double olduğunda bu çalışma durur.
Rick Moritz

OP cevap vermiyor: RDD hakkında konuşuyor [Satır]
javadba

6

Yöntem 1: (Scala)

val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext.implicits._
val df_2 = sc.parallelize(Seq((1L, 3.0, "a"), (2L, -1.0, "b"), (3L, 0.0, "c"))).toDF("x", "y", "z")

Yöntem 2: (Scala)

case class temp(val1: String,val3 : Double) 

val rdd = sc.parallelize(Seq(
  Row("foo",  0.5), Row("bar",  0.0)
))
val rows = rdd.map({case Row(val1:String,val3:Double) => temp(val1,val3)}).toDF()
rows.show()

Yöntem 1: (Python)

from pyspark.sql import Row
l = [('Alice',2)]
Person = Row('name','age')
rdd = sc.parallelize(l)
person = rdd.map(lambda r:Person(*r))
df2 = sqlContext.createDataFrame(person)
df2.show()

Yöntem 2: (Python)

from pyspark.sql.types import * 
l = [('Alice',2)]
rdd = sc.parallelize(l)
schema =  StructType([StructField ("name" , StringType(), True) , 
StructField("age" , IntegerType(), True)]) 
df3 = sqlContext.createDataFrame(rdd, schema) 
df3.show()

Satır nesnesinden değeri ayıkladı ve rdd'yi DF'ye dönüştürmek için case sınıfını uyguladı

val temp1 = attrib1.map{case Row ( key: Int ) => s"$key" }
val temp2 = attrib2.map{case Row ( key: Int) => s"$key" }

case class RLT (id: String, attrib_1 : String, attrib_2 : String)
import hiveContext.implicits._

val df = result.map{ s => RLT(s(0),s(1),s(2)) }.toDF

4

Kıvılcımın daha yeni sürümlerinde (2.0+)

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
import org.apache.spark.sql._
import org.apache.spark.sql.types._

val spark = SparkSession
  .builder()
  .getOrCreate()
import spark.implicits._

val dfSchema = Seq("col1", "col2", "col3")
rdd.toDF(dfSchema: _*)

1
sparkSession SqlContext, hiveContext için sadece bir sarıcı
Archit

1
One needs to create a schema, and attach it to the Rdd.

Val spark'un bir SparkSession.builder ürünü olduğu varsayılarak ...

    import org.apache.spark._
    import org.apache.spark.sql._       
    import org.apache.spark.sql.types._

    /* Lets gin up some sample data:
     * As RDD's and dataframes can have columns of differing types, lets make our
     * sample data a three wide, two tall, rectangle of mixed types.
     * A column of Strings, a column of Longs, and a column of Doubules 
     */
    val arrayOfArrayOfAnys = Array.ofDim[Any](2,3)
    arrayOfArrayOfAnys(0)(0)="aString"
    arrayOfArrayOfAnys(0)(1)=0L
    arrayOfArrayOfAnys(0)(2)=3.14159
    arrayOfArrayOfAnys(1)(0)="bString"
    arrayOfArrayOfAnys(1)(1)=9876543210L
    arrayOfArrayOfAnys(1)(2)=2.71828

    /* The way to convert an anything which looks rectangular, 
     * (Array[Array[String]] or Array[Array[Any]] or Array[Row], ... ) into an RDD is to 
     * throw it into sparkContext.parallelize.
     * http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.SparkContext shows
     * the parallelize definition as 
     *     def parallelize[T](seq: Seq[T], numSlices: Int = defaultParallelism)
     * so in our case our ArrayOfArrayOfAnys is treated as a sequence of ArraysOfAnys.
     * Will leave the numSlices as the defaultParallelism, as I have no particular cause to change it. 
     */
    val rddOfArrayOfArrayOfAnys=spark.sparkContext.parallelize(arrayOfArrayOfAnys)

    /* We'll be using the sqlContext.createDataFrame to add a schema our RDD.
     * The RDD which goes into createDataFrame is an RDD[Row] which is not what we happen to have.
     * To convert anything one tall and several wide into a Row, one can use Row.fromSeq(thatThing.toSeq)
     * As we have an RDD[somethingWeDontWant], we can map each of the RDD rows into the desired Row type. 
     */     
    val rddOfRows=rddOfArrayOfArrayOfAnys.map(f=>
        Row.fromSeq(f.toSeq)
    )

    /* Now to construct our schema. This needs to be a StructType of 1 StructField per column in our dataframe.
     * https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.types.StructField shows the definition as
     *   case class StructField(name: String, dataType: DataType, nullable: Boolean = true, metadata: Metadata = Metadata.empty)
     * Will leave the two default values in place for each of the columns:
     *        nullability as true, 
     *        metadata as an empty Map[String,Any]
     *   
     */

    val schema = StructType(
        StructField("colOfStrings", StringType) ::
        StructField("colOfLongs"  , LongType  ) ::
        StructField("colOfDoubles", DoubleType) ::
        Nil
    )

    val df=spark.sqlContext.createDataFrame(rddOfRows,schema)
    /*
     *      +------------+----------+------------+
     *      |colOfStrings|colOfLongs|colOfDoubles|
     *      +------------+----------+------------+
     *      |     aString|         0|     3.14159|
     *      |     bString|9876543210|     2.71828|
     *      +------------+----------+------------+
    */ 
    df.show 

Aynı adımlar, ancak daha az val bildirimi ile:

    val arrayOfArrayOfAnys=Array(
        Array("aString",0L         ,3.14159),
        Array("bString",9876543210L,2.71828)
    )

    val rddOfRows=spark.sparkContext.parallelize(arrayOfArrayOfAnys).map(f=>Row.fromSeq(f.toSeq))

    /* If one knows the datatypes, for instance from JDBC queries as to RDBC column metadata:
     * Consider constructing the schema from an Array[StructField].  This would allow looping over 
     * the columns, with a match statement applying the appropriate sql datatypes as the second
     *  StructField arguments.   
     */
    val sf=new Array[StructField](3)
    sf(0)=StructField("colOfStrings",StringType)
    sf(1)=StructField("colOfLongs"  ,LongType  )
    sf(2)=StructField("colOfDoubles",DoubleType)        
    val df=spark.sqlContext.createDataFrame(rddOfRows,StructType(sf.toList))
    df.show

1

Çözümü kelime sayımı problemini kullanarak açıklamaya çalıştım . 1. sc kullanarak dosyayı okuyun

  1. Kelime sayısı üretin
  2. DF oluşturma yöntemleri

    • rdd.toDF yöntemi
    • rdd.toDF ( "kelime", "saymak")
      • spark.createDataFrame (RDD, şema)

    Kıvılcım kullanarak dosyayı okuma

    val rdd=sc.textFile("D://cca175/data/")  

    RDD - Veri Çerçevesi

    val df = sc.textFile ("D: // cca175 / data /") .toDF ("t1") df.show

    Yöntem 1

    Dataframe için kelime sayısı RDD oluşturma

    val df=rdd.flatMap(x=>x.split(" ")).map(x=>(x,1)).reduceByKey((x,y)=>(x+y)).toDF("word","count")

    Method2

    RDD'den Veri Çerçevesi Oluşturma

    val df=spark.createDataFrame(wordRdd) 
    # with header   
    val df=spark.createDataFrame(wordRdd).toDF("word","count")  df.show

    Method3

    Şemayı Tanımla

    import org.apache.spark.sql.types._

    val schema = new StructType (). (StructField ( "kelime", StringType, true)) ekleyin. (StructField ( "sayısı", StringType, true)) ekleyin

    RowRDD Oluştur

    import org.apache.spark.sql.Row
    val rowRdd=wordRdd.map(x=>(Row(x._1,x._2)))     

    Şema ile RDD'den DataFrame oluşturma

    val df = spark.createDataFrame (rowRdd, şema)
    df.show


0

Bir Diziyi [Satır] 'ı DataFrame veya Veri Kümesine dönüştürmek için aşağıdakiler zarif bir şekilde çalışır:

Diyelim ki şema satırın StructType'ı, sonra

val rows: Array[Row]=...
implicit val encoder = RowEncoder.apply(schema)
import spark.implicits._
rows.toDS
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.