Dataframe sütun değerlerini Apache Spark'ta Liste olarak çıkarın


87

Bir veri çerçevesinin dize sütununu listeye dönüştürmek istiyorum. DataframeAPI'den bulabildiğim şey RDD, bu yüzden önce onu RDD'ye dönüştürmeyi ve ardından toArrayRDD'ye işlevi uygulamayı denedim . Bu durumda uzunluk ve SQL gayet iyi çalışıyor. Ancak, RDD'den aldığım sonuç, bunun gibi her öğenin etrafında köşeli parantezler içeriyor [A00001]. Bir sütunu listeye dönüştürmenin uygun bir yolu veya köşeli parantezleri kaldırmanın bir yolu olup olmadığını merak ediyordum.

Herhangi bir öneri memnuniyetle karşılanacaktır. Teşekkür ederim!


Yanıtlar:


117

Bu, tek liste içeren koleksiyonu döndürmelidir:

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

Eşleştirme olmadan, veritabanındaki her sütunu içeren bir Row nesnesi alırsınız.

Bunun size muhtemelen Herhangi bir tür listesi getireceğini unutmayın. Eğer sonuç türünü belirtmek isterseniz, içeri .asInstanceOf [YOUR_TYPE] kullanabilirsiniz r => r(0).asInstanceOf[YOUR_TYPE]haritalama

PS otomatik dönüştürme sayesinde .rddparçayı atlayabilirsiniz .


3
Garip bir nedenden ötürü ters yönde çalışır (Spark 2.1.0) collect().map(r => r(0))- bu siparişin herhangi bir dezavantajı var mı?
Boern

1
Daha yavaş olabilir - çözümünüz önce sürücüdeki tüm verileri toplar ve bundan sonra yalnızca tek bir sürücünün işlem gücünü kullanarak sürücü üzerinde (yürütmenin yardımı olmadan) eşleştirme yapar.
TheMP

73

Spark 2.x ve Scala 2.11 ile

Belirli bir sütunun değerlerini Listeye dönüştürmek için 3 olası yol düşünüyorum.

Tüm yaklaşımlar için ortak kod parçacıkları

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDF() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5), 
    ("choose", 8.0)
  ).toDF("id", "val")

Yaklaşım 1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)

Şimdi ne olacak? Sürücüye veri collect()topluyoruz ve her kayıttan sıfır elemanı seçiyoruz.

Bu, bunu yapmanın mükemmel bir yolu olamaz. Bir sonraki yaklaşımla bunu geliştirelim.


Yaklaşım 2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)

Nasıl daha iyi? İşçiler arasında tek Sürücü yerine harita dönüşüm yükünü dağıttık.

Ben biliyorum rdd.map(r => r(0))sen değil zarif görünüyor yapar. Öyleyse, bir sonraki yaklaşımda bunu ele alalım.


Yaklaşım 3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)

Burada DataFrame'i RDD'ye dönüştürmüyoruz. Bak mapo kabul etmeyecektir r => r(0)(veya _(0)bağlı DataFrame içinde kodlayıcı konulara önceki yaklaşım olarak). Bu yüzden kullanmayı r => r.getString(0)bırakın ve Spark'ın sonraki sürümlerinde ele alınacaktır.

Sonuç

Tüm seçenekler aynı çıktıyı veriyor ancak 2 ve 3 etkili, son olarak üçüncü seçenek etkili ve zarif (bence).

Databricks not defteri


24

Verilen ve istenen cevabın Scala için varsayıldığını biliyorum, bu yüzden bir PySpark kullanıcısının merak etmesi durumunda sadece Python kodunun küçük bir parçasını veriyorum. Sözdizimi verilen yanıta benzer, ancak listeyi düzgün bir şekilde açmak için eşleme işlevinde sütun adına ikinci kez başvurmam gerekiyor ve select deyimine ihtiyacım yok.

ör. "Raw" adlı bir sütun içeren bir DataFrame

"Raw" daki her satır değerini, her girişin "Raw" dan bir satır değeri olduğu bir liste olarak birleştirmek için şunu kullanıyorum:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()

4
Bu, Row nesnelerinin bir listesini verir. Ya değerlerin bir listesini istersen?
ThatDataGuy

Bu bir değerler listesi verir.
abby sobh

Bunu paylaştığınız için teşekkürler! Bu benim için harika çalışıyor, sadece bunu hızlandırmanın bir yolu olup olmadığını merak ediyorum, oldukça yavaş çalışıyor
Mojgan Mazouchi

5

Scala ve Spark 2+ içinde şunu deneyin (sütun adınızın "s" olduğunu varsayarak): df.select('s).as[String].collect


3
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

mükemmel çalışıyor


2
from pyspark.sql.functions import col

df.select(col("column_name")).collect()

burada toplamak, sırayla listeye dönüştüren işlevlerdir. Büyük veri kümesindeki listeyi kullanmaktan çekinmeyin. Performansı düşürecektir. Verileri kontrol etmek iyidir.


1
List<String> whatever_list = df.toJavaRDD().map(new Function<Row, String>() {
    public String call(Row row) {
        return row.getAs("column_name").toString();
    }
}).collect();

logger.info(String.format("list is %s",whatever_list)); //verification

Java'da (Gerçek Programlama Dili) kimse çözüm vermediği için bana daha sonra teşekkür edebilir misiniz?


0

Size bir liste veren güncellenmiş bir çözüm:

dataFrame.select("YOUR_COLUMN_NAME").map(r => r.getString(0)).collect.toList


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.