簡體   English   中英

給特定單元格賦值 PySpark dataFrame

[英]Assign value to specific cell in PySpark dataFrame

我想使用PySpark更改我的Spark DataFrame的特定單元格中的值。

簡單的例子——我創建了一個模擬Spark DataFrame

df = spark.createDataFrame(
    [
     (1, 1.87, 'new_york'), 
     (4, 2.76, 'la'), 
     (6, 3.3, 'boston'), 
     (8, 4.1, 'detroit'), 
     (2, 5.70, 'miami'), 
     (3, 6.320, 'atlanta'), 
     (1, 6.1, 'houston')
    ],
    ('variable_1', "variable_2", "variable_3")
)

Runnning display(df)我得到這張表:

variable_1   variable_2   variable_3
    1           1.87    new_york
    4           2.76    la
    6           3.3     boston
    8           4.1     detroit
    2           5.7     miami
    3           6.32    atlanta
    1           6.1     houston

比方說,我想為第 4 行和第 3 列中的單元格分配一個新值,即將detroit更改為new_orleans 我知道df.iloc[4, 3] = 'new_orleans'df.loc[4, 'detroit'] = 'new_orleans'Spark中無效。

使用when對我的問題的有效答案是:

from pyspark.sql.functions import when
targetDf = df.withColumn("variable_3", \
              when(((df["variable_1"] == 8) & (df["variable_2"] == 4.1)) , 'new_orleans').otherwise(df["variable_3"]))

我的問題是:這是否可以在PySpark中以更實用的方式完成,而無需輸入我只想更改 1 個單元格的行的所有值和列名(可能在不使用when函數的情況下實現相同)?

預先感謝您的幫助和@useruser9806664 的反饋。

Spark DataFrames不可變的不提供隨機訪問 ,嚴格來說,它是無序的 結果是:

  • 您不能分配任何內容(因為屬性是不可變的)。
  • 您無法訪問特定的行(因為沒有隨機訪問權限)。
  • 行“ indcies”的定義不明確(因為無序)。

您可以做的是使用新的列創建一個新的數據框,使用一些條件表達式替換現有的數據框,該條件表達式已包含在您找到的答案中。

另外, monotonically_increasing_id不會添加索引(行號)。 它添加單調遞增的數字,不一定是連續的數字或從任何特定值開始(如果是空分區)。

考慮使用 Pandas DataFrame

Spark DataFrame 確實是不可變的,因此,它們不是為修改而設計的。 Spark Dataframes 是分布式數據 collections 針對處理大量數據進行了優化,如果您想進行任何更改,則必須創建一個包含所需修改的新數據框。

然而,有時您可能需要修改特定行的特定單元格。 對於這些情況,您可以使用when function(就像您在示例中所做的那樣)使用與您要修改的特定單元格位於同一行的單元格值來修改該列。 或者您可以考慮將您的 Spark Dataframe 轉換為 Pandas DataFrame (它們是可變的),並在將新值分配給相關單元格后,將其轉換回 Spark DataFrame 這是您可以如何做到的:

# Copy the schema of your Spark dataframe 
schema = df.schema

# Create Pandas Dataframe using your Spark DataFrame
pandas_df = df.toPandas()

# Assign the new value to the specific cell (you could use .at or .loc)
pandas_df.at[3, 'variable_3'] = 'new_orleans'

# Update your dataframe with the new value using the Pandas DataFrame
df = spark.createDataFrame(pandas_df,schema=schema)

# Delete the auxiliary pandas dataframe to free memory for other uses
del pandas_df

請記住,Pandas DataFrames 不是分布式的,在 Pandas DataFrame 處理大量數據會更慢。

您可以使用基礎的RDD創建行號:

from pyspark.sql import Row

# Function to update dataframe row with a rownumber
def create_rownum(ziprow):
    row, index=ziprow
    row=row.asDict()
    row['rownum']= index
    return(Row(**row))

# First create a rownumber then add to dataframe
df.rdd.zipWithIndex().map(create_rownum).toDF().show()

現在,您可以過濾DataFrame以獲得所需的行號。

我遇到了同樣的問題,但我使用了 sql 表達式:

expr = """CASE WHEN variable1==8 AND variable==4.1 THEN 'new_orleans' ELSE variable3 END AS variable4"""

df = df.selectExpr(*,expr)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM