ตอนนี้ฉันต้องใช้df.count > 0
เพื่อตรวจสอบว่าDataFrame
ว่างหรือไม่ แต่มันไม่มีประสิทธิภาพ มีวิธีไหนที่ดีกว่านี้ไหม?
ขอบคุณ.
PS: ฉันต้องการตรวจสอบว่าว่างหรือไม่เพื่อที่ฉันจะบันทึกเฉพาะDataFrame
ถ้ามันไม่ว่าง
ตอนนี้ฉันต้องใช้df.count > 0
เพื่อตรวจสอบว่าDataFrame
ว่างหรือไม่ แต่มันไม่มีประสิทธิภาพ มีวิธีไหนที่ดีกว่านี้ไหม?
ขอบคุณ.
PS: ฉันต้องการตรวจสอบว่าว่างหรือไม่เพื่อที่ฉันจะบันทึกเฉพาะDataFrame
ถ้ามันไม่ว่าง
คำตอบ:
สำหรับ Spark 2.1.0 ข้อเสนอแนะของฉันคือใช้head(n: Int)
หรือtake(n: Int)
กับข้อisEmpty
ใดก็ได้ที่มีเจตนาชัดเจนที่สุดสำหรับคุณ
df.head(1).isEmpty
df.take(1).isEmpty
เทียบเท่ากับ Python:
len(df.head(1)) == 0 # or bool(df.head(1))
len(df.take(1)) == 0 # or bool(df.take(1))
การใช้df.first()
และdf.head()
ทั้งสองจะส่งคืนjava.util.NoSuchElementException
หาก DataFrame ว่างเปล่า first()
โทรhead()
โดยตรงซึ่งโทรhead(1).head
.
def first(): T = head()
def head(): T = head(1).head
head(1)
ส่งคืน Array ดังนั้นการรับhead
Array จะทำให้java.util.NoSuchElementException
เมื่อ DataFrame ว่างเปล่า
def head(n: Int): Array[T] = withAction("head", limit(n).queryExecution)(collectFromPlan)
ดังนั้นแทนที่จะโทรhead()
ให้ใช้head(1)
โดยตรงเพื่อรับอาร์เรย์จากนั้นคุณสามารถisEmpty
ใช้ได้
take(n)
ยังเทียบเท่ากับhead(n)
...
def take(n: Int): Array[T] = head(n)
และlimit(1).collect()
เทียบเท่ากับhead(1)
(ข้อสังเกตlimit(n).queryExecution
ในhead(n: Int)
วิธีการ) ดังนั้นสิ่งต่อไปนี้จึงเทียบเท่าทั้งหมดอย่างน้อยก็จากสิ่งที่ฉันบอกได้และคุณจะไม่ต้องพบjava.util.NoSuchElementException
ข้อยกเว้นเมื่อ DataFrame ว่างเปล่า
df.head(1).isEmpty
df.take(1).isEmpty
df.limit(1).collect().isEmpty
ฉันรู้ว่านี่เป็นคำถามที่เก่ากว่าดังนั้นหวังว่าจะช่วยให้ผู้ใช้ Spark เวอร์ชันใหม่กว่านี้ได้
df.rdd.isEmpty
?
df.head(1)
ใช้เวลามากอาจเป็นเพราะdf
แผนการดำเนินการของคุณกำลังทำบางสิ่งที่ซับซ้อนซึ่งป้องกันไม่ให้ประกายไฟจากการใช้ทางลัด ตัวอย่างเช่นหากคุณเพิ่งอ่านจากไฟล์ไม้ปาร์เก้df = spark.read.parquet(...)
ฉันค่อนข้างมั่นใจว่า spark จะอ่านพาร์ติชันไฟล์เดียวเท่านั้น แต่ถ้าคุณdf
กำลังทำสิ่งอื่น ๆ เช่นการรวมคุณอาจถูกบังคับโดยไม่ได้ตั้งใจบังคับให้ Spark อ่านและประมวลผลแหล่งข้อมูลส่วนใหญ่หากไม่ใช่ทั้งหมด
df.limit(1).count()
อย่างไร้เดียงสา ในชุดข้อมูลขนาดใหญ่ต้องใช้เวลามากกว่าตัวอย่างที่รายงานโดย @ hulin003 ซึ่งเกือบจะเกิดขึ้นในทันที
RDD
ผมจะบอกว่าเพียงแค่คว้าพื้นฐาน ใน Scala:
df.rdd.isEmpty
ใน Python:
df.rdd.isEmpty()
ที่พูดมาทั้งหมดนี้คือการโทรtake(1).length
ดังนั้นมันจะทำแบบเดียวกับที่โรฮันตอบ ... อาจจะชัดเจนกว่านี้เล็กน้อย?
คุณสามารถใช้ประโยชน์จากฟังก์ชันhead()
(หรือfirst()
) เพื่อดูว่าDataFrame
มีแถวเดียวหรือไม่ ถ้าเป็นเช่นนั้นก็ไม่ว่างเปล่า
ตั้งแต่ Spark 2.4.0 มีDataset.isEmpty
.
มันดำเนินการคือ
def isEmpty: Boolean =
withAction("isEmpty", limit(1).groupBy().count().queryExecution) { plan =>
plan.executeCollect().head.getLong(0) == 0
}
โปรดทราบว่า a DataFrame
ไม่ใช่คลาสใน Scala อีกต่อไป แต่เป็นเพียงนามแฝงประเภท (อาจเปลี่ยนด้วย Spark 2.0):
type DataFrame = Dataset[Row]
ถ้าคุณทำdf.count > 0
. จะนับพาร์ติชันทั้งหมดในตัวดำเนินการทั้งหมดและเพิ่มที่ Driver การดำเนินการนี้ใช้เวลาสักครู่เมื่อคุณจัดการกับแถวนับล้าน
วิธีที่ดีที่สุดคือดำเนินการdf.take(1)
และตรวจสอบว่าโมฆะหรือไม่ สิ่งนี้จะกลับมาjava.util.NoSuchElementException
ดีกว่าที่จะลองdf.take(1)
ใช้
dataframe ส่งคืนข้อผิดพลาดเมื่อtake(1)
เสร็จสิ้นแทนที่จะเป็นแถวว่าง ฉันได้เน้นบรรทัดรหัสเฉพาะที่มันแสดงข้อผิดพลาด
count
วิธีนี้จะใช้เวลาพอสมควร
สำหรับผู้ใช้ Java คุณสามารถใช้สิ่งนี้กับชุดข้อมูล:
public boolean isDatasetEmpty(Dataset<Row> ds) {
boolean isEmpty;
try {
isEmpty = ((Row[]) ds.head(1)).length == 0;
} catch (Exception e) {
return true;
}
return isEmpty;
}
สิ่งนี้ตรวจสอบสถานการณ์ที่เป็นไปได้ทั้งหมด (ว่างเปล่าว่าง)
ใน Scala คุณสามารถใช้นัยเพื่อเพิ่มวิธีการisEmpty()
และnonEmpty()
ไปยัง DataFrame API ซึ่งจะทำให้โค้ดอ่านง่ายขึ้น
object DataFrameExtensions {
implicit def extendedDataFrame(dataFrame: DataFrame): ExtendedDataFrame =
new ExtendedDataFrame(dataFrame: DataFrame)
class ExtendedDataFrame(dataFrame: DataFrame) {
def isEmpty(): Boolean = dataFrame.head(1).isEmpty // Any implementation can be used
def nonEmpty(): Boolean = !isEmpty
}
}
ที่นี่สามารถเพิ่มวิธีการอื่น ๆ ได้เช่นกัน หากต้องการใช้การแปลงโดยนัยให้ใช้import DataFrameExtensions._
ในไฟล์ที่คุณต้องการใช้ฟังก์ชันเพิ่มเติม หลังจากนั้นสามารถใช้วิธีการได้โดยตรงดังนี้:
val df: DataFrame = ...
if (df.isEmpty) {
// Do something
}
ฉันมีคำถามเดียวกันและฉันทดสอบ 3 วิธีแก้ปัญหาหลัก:
และแน่นอนว่าทั้ง 3 ทำงานได้อย่างไรก็ตามในแง่ของความสมบูรณ์นี่คือสิ่งที่ฉันพบเมื่อดำเนินการตามวิธีการเหล่านี้บน DF เดียวกันในเครื่องของฉันในระยะเวลาดำเนินการ:
ดังนั้นฉันคิดว่าทางออกที่ดีที่สุดคือdf.rdd.isEmpty ตามที่ @Justin Pihony แนะนำ
ฉันพบว่าในบางกรณี:
>>>print(type(df))
<class 'pyspark.sql.dataframe.DataFrame'>
>>>df.take(1).isEmpty
'list' object has no attribute 'isEmpty'
สิ่งนี้เหมือนกันสำหรับ "length" หรือแทนที่ take () by head ()
[วิธีแก้ไข] สำหรับปัญหาที่เราสามารถใช้ได้
>>>df.limit(2).count() > 1
False
หากคุณใช้ Pypsark คุณสามารถทำได้:
len(df.head(1)) > 0
เมื่อวันที่ PySpark คุณยังสามารถใช้วิธีนี้bool(df.head(1))
จะได้รับTrue
ของFalse
มูลค่า
จะส่งคืนFalse
หาก dataframe ไม่มีแถว
df1.take(1).length>0
วิธีการส่งกลับอาร์เรย์ของแถวดังนั้นถ้าขนาดอาร์เรย์เท่ากับศูนย์มีบันทึกในไม่มีtake
df
dataframe.limit(1).count > 0
สิ่งนี้ยังทำให้เกิดงาน แต่เนื่องจากเรากำลังเลือกระเบียนเดียวแม้ว่าในกรณีที่มีการบันทึกระดับพันล้านการใช้เวลาอาจลดลงมาก
คุณสามารถทำได้เช่น:
val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
println("empty df ")
else
println("normal df")
schema
สองดาต้าเฟรม ( sqlContext.emptyDataFrame
& df
) เหมือนกันเพื่อที่จะกลับมาอีกtrue
หรือไม่?
eq
ได้รับการสืบทอดมาจากAnyRef
และทดสอบว่าอาร์กิวเมนต์ (นั้น) เป็นการอ้างอิงถึงวัตถุตัวรับหรือไม่ (สิ่งนี้)