当前位置: 首页 > 知识库问答 >
问题:

将元数据附加到Spark中的向量列

仲孙兴旺
2023-03-14

上下文:我有一个包含两列的数据帧:标签和特性。

org.apache.spark.sql.DataFrame = [label: int, features: vector]
val defaultAttr = NumericAttribute.defaultAttr
val attrs = Array("feat1", "feat2", "feat3").map(defaultAttr.withName)
val attrGroup = new AttributeGroup("userFeatures", attrs.asInstanceOf[Array[Attribute]])
scala> attrGroup.toMetadata 
res197: org.apache.spark.sql.types.Metadata = {"ml_attr":{"attrs":{"numeric":[{"idx":0,"name":"f1"},{"idx":1,"name":"f2"},{"idx":2,"name":"f3"}]},"num_attrs":3}}

共有1个答案

乜业
2023-03-14

至少有两个选择:

>

  • 在现有的dataframe上,可以使用as方法和metadata参数:

    import org.apache.spark.ml.attribute._
    
    val rdd = sc.parallelize(Seq(
      (1, Vectors.dense(1.0, 2.0, 3.0))
    ))
    val df = rdd.toDF("label", "features")
    
    df.withColumn("features", $"features".as("_", attrGroup.toMetadata))
    

    创建新的DataFrame时,转换AttributeGroupToStructField并将其用作给定列的架构:

    import org.apache.spark.sql.types.{StructType, StructField, IntegerType}
    
    val schema = StructType(Array(
      StructField("label", IntegerType, false),
      attrGroup.toStructField()
    ))
    
    spark.createDataFrame(
      rdd.map(row => Row.fromSeq(row.productIterator.toSeq)),
      schema)
    
    import org.apache.spark.ml.feature.VectorAssembler
    
    val raw = sc.parallelize(Seq(
      (1, 1.0, 2.0, 3.0)
    )).toDF("id", "feat1", "feat2", "feat3")
    
    val assembler = new VectorAssembler()
      .setInputCols(Array("feat1", "feat2", "feat3"))
      .setOutputCol("features")
    
    val dfWithMeta = assembler.transform(raw).select($"id", $"features")
    dfWithMeta.schema.fields(1).metadata
    
    // org.apache.spark.sql.types.Metadata = {"ml_attr":{"attrs":{"numeric":[
    //   {"idx":0,"name":"feat1"},{"idx":1,"name":"feat2"},
    //   {"idx":2,"name":"feat3"}]},"num_attrs":3}
    

    向量字段不能使用点语法直接访问(如$features.feat1),但可以由VectorSlicer:

    import org.apache.spark.ml.feature.VectorSlicer
    
    val slicer = new VectorSlicer()
      .setInputCol("features")
      .setOutputCol("featuresSubset")
      .setNames(Array("feat1", "feat3"))
    
    slicer.transform(dfWithMeta).show
    // +---+-------------+--------------+
    // | id|     features|featuresSubset|
    // +---+-------------+--------------+
    // |  1|[1.0,2.0,3.0]|     [1.0,3.0]|
    // +---+-------------+--------------+
    

    有关PySpark,请参见如何将列声明为DataFrame中的分类特性,以便在ml中使用

  •  类似资料:
    • 问题内容: 我试图基于一个的数据创建“ n” 。我正在检查in的Integer值,并循环执行sql语句以创建与列中一样多的“ n” 。 这是我的代码: 我需要创建“ n”,但我不知道如何在循环之前声明类型并在for内填充。 现有数据类型: 新的数据类型: 问题答案: 您可以创建一个可变列表并填充它: 但是更好的方法(不使用可变数据结构)是将整数列表 映射 到DataFrames列表中:

    • 我使用的是Spark 1.6,我想在数据帧中添加一列。新列实际上是一个常量序列:Seq(“-0”、“-1”、“-2”、“-3”) 这是我的原始数据帧: root--user\u name:string(nullable=true) |--test\u name:string(nullable=true) |user_name|test_name| ------------ ------------

    • 我已经创建了一个XML解析器来将XML文件中的信息检索到java,然后我尝试将这些数据存储到ArrayList中,以便将ArrayList用于我的方法。当我打印出来时,它似乎工作得很好。然而,由于某种原因,我得到了一个名为getAllRoutes的方法,它返回了错误的路由数

    • 编辑:使用工作,不知道它是如何工作的

    • MATLAB允许您将向量追加到一起以创建新向量。 如果你有两个行向量r1和r2,其中包含n和m个元素,要创建一个n加m个元素的行向量r,通过附加这些向量,你可以写 - r = [r1,r2] 您还可以通过附加这两个向量来创建矩阵r,向量r2将是矩阵的第二行 - r = [r1;r2] 但是,为此,两个向量应具有相同数量的元素。 类似地,您可以使用n和m个元素追加两个列向量c1和c2。 要创建n

    • 问题内容: 我将如何继续追加数据?我有这个: 我想向它添加另一个对象,例如: 这是我使用的代码: 我真的不知道如何继续添加它,但是也许其他人知道吗? 问题答案: 您将无法使用文件追加操作来执行此操作。文件追加操作只能在末尾添加文本,而不能在中间插入文本。这使得不可能使用file-append来保持JSON有效。 我可以想到两种选择: 将整个文件读入一个对象,添加您的对象,然后重写整个文件(性能不佳