Python 更新spark中的数据帧列
查看新的spark dataframe api,不清楚是否可以修改dataframe列 如何更改数据帧的行Python 更新spark中的数据帧列,python,apache-spark,pyspark,apache-spark-sql,spark-dataframe,Python,Apache Spark,Pyspark,Apache Spark Sql,Spark Dataframe,查看新的spark dataframe api,不清楚是否可以修改dataframe列 如何更改数据帧的行x列y中的值 在pandas中,这将是df.ix[x,y]=新值 编辑:整合下面所说的内容,您不能修改现有的数据帧,因为它是不可变的,但是您可以返回一个带有所需修改的新数据帧 如果您只想根据条件替换列中的值,如np。其中: from pyspark.sql import functions as F update_func = (F.when(F.col('update_col') ==
x
列y
中的值
在pandas
中,这将是df.ix[x,y]=新值
编辑:整合下面所说的内容,您不能修改现有的数据帧,因为它是不可变的,但是您可以返回一个带有所需修改的新数据帧
如果您只想根据条件替换列中的值,如np。其中
:
from pyspark.sql import functions as F
update_func = (F.when(F.col('update_col') == replace_val, new_value)
.otherwise(F.col('update_col')))
df = df.withColumn('new_column_name', update_func)
如果要对列执行某些操作并创建添加到数据帧的新列,请执行以下操作:
import pyspark.sql.functions as F
import pyspark.sql.types as T
def my_func(col):
do stuff to column here
return transformed_value
# if we assume that my_func returns a string
my_udf = F.UserDefinedFunction(my_func, T.StringType())
df = df.withColumn('new_column_name', my_udf('update_col'))
如果希望新列与旧列具有相同的名称,可以添加附加步骤:
df = df.drop('update_col').withColumnRenamed('new_column_name', 'update_col')
数据帧
基于RDD。RDD是不可变的结构,不允许在现场更新元素。要更改值,您需要通过使用类似SQL的DSL或类似于map
的RDD操作转换原始数据帧来创建新的数据帧
强烈推荐的幻灯片组:。虽然您不能修改列本身,但可以对列进行操作并返回反映该更改的新数据帧。为此,您首先创建一个UserDefinedFunction
实现要应用的操作,然后有选择地仅将该函数应用于目标列。在Python中:
from pyspark.sql.functions import UserDefinedFunction
from pyspark.sql.types import StringType
name = 'target_column'
udf = UserDefinedFunction(lambda x: 'new_value', StringType())
new_df = old_df.select(*[udf(column).alias(name) if column == name else column for column in old_df.columns])
new_-df
现在具有与old_-df
相同的模式(假设old_-df.target_列
也是StringType
)但是列target\u列
中的所有值都将是new\u值
,就像您可以从应用于旧数据帧的映射结果创建新数据帧一样。具有两行的给定数据帧df
示例:
val newDf = sqlContext.createDataFrame(df.map(row =>
Row(row.getInt(0) + SOMETHING, applySomeDef(row.getAs[Double]("y")), df.schema)
请注意,如果列的类型发生更改,则需要为其提供正确的模式,而不是df.schema
。查看org.apache.spark.sql.Row
的api以了解可用的方法:
[更新]或在Scala中使用UDF:
import org.apache.spark.sql.functions._
val toLong = udf[Long, String] (_.toLong)
val modifiedDf = df.withColumn("modifiedColumnName", toLong(df("columnName"))).drop("columnName")
如果列名需要保持不变,可以重新命名:
modifiedDf.withColumnRenamed("modifiedColumnName", "columnName")
通常在更新列时,我们希望将旧值映射到新值。在pyspark中,有一种方法可以在没有UDF的情况下实现这一点:
# update df[update_col], mapping old_value --> new_value
from pyspark.sql import functions as F
df = df.withColumn(update_col,
F.when(df[update_col]==old_value,new_value).
otherwise(df[update_col])).
从pyspark.sql.functions导入col时,并基于字符串(字符串a、字符串b、字符串c)将第五列更新为整数(0,1,2)到新的数据帧中
from pyspark.sql.functions import col, when
data_frame_temp = data_frame.withColumn("col_5",when(col("col_5") == "string a", 0).when(col("col_5") == "string b", 1).otherwise(2))
那么,究竟是什么样的数据帧抽象添加了无法在相同数量的表行中完成的内容呢?“数据帧引入了新的简化运算符,用于对大型数据集进行过滤、聚合和投影。在内部,DataFrames利用Spark SQL逻辑优化器智能地规划操作的物理执行,以便在大型数据集上正常工作“-这是问题的实际答案,谢谢!然而,火花工作对我来说还没有结束,所有的遗嘱执行人都会得到los。你能想出另一种方法吗?我将它与更复杂的UDF一起使用,在UDF中我对字符串进行转换。没有类似的语法,比如new_df=old_df.col1.apply(lambda x:func(x))?还有:new_df=old_df.withColumn('target_column',udf(df.name))
Yes,应该可以正常工作。请记住,UDF只能将列作为参数。如果要将其他数据传递到函数中,则必须首先部分应用它。@KatyaHandler如果只想复制列,一种方法是只需选择它两次:df.select([df[col],df[col].alias('same_column')))
,其中col
是要复制的列的名称。在最新的Spark发行版中,我使用UDF的很多东西都可以通过pyspark.sql.functions
中定义的函数来完成。Pyspark中的UDF性能非常差,因此可能确实值得研究:在UDF=UserDefinedFunction(lambda x:'new_value',StringType())
中,它是StringType
而不是StringType
。
如果要按索引访问数据帧,需要首先构建索引。参见,例如。或者使用您自己的索引添加一个索引列。当我的更新列是一个列表Ex-=:update\u cols=['col1'、'col2'、'col3']
时,如何使用此列?使用for循环。