Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spark RDD到CSV-添加空列_Csv_Apache Spark - Fatal编程技术网

Spark RDD到CSV-添加空列

Spark RDD到CSV-添加空列,csv,apache-spark,Csv,Apache Spark,我有一个RDD[Map[String,Int]],其中映射的键是列名。每个映射都不完整,要知道列名,我需要合并所有键。有没有一种方法可以避免这种收集操作,即知道所有密钥并只使用一次rdd.saveAsTextFile(..)来获取csv 例如,假设我有一个包含两个元素的RDD(scala表示法): 我想以这个csv结束: a,b,c 1,2,0 0,1,3 Scala解决方案更好,但任何其他兼容Spark的语言都可以 编辑: 我也可以尝试从另一个方向解决我的问题。假设我知道开头的所有列,但我想

我有一个RDD[Map[String,Int]],其中映射的键是列名。每个映射都不完整,要知道列名,我需要合并所有键。有没有一种方法可以避免这种收集操作,即知道所有密钥并只使用一次rdd.saveAsTextFile(..)来获取csv

例如,假设我有一个包含两个元素的RDD(scala表示法):

我想以这个csv结束:

a,b,c
1,2,0
0,1,3
Scala解决方案更好,但任何其他兼容Spark的语言都可以

编辑:

我也可以尝试从另一个方向解决我的问题。假设我知道开头的所有列,但我想去掉所有映射中值为0的列。所以问题变成了,我知道键是(“a”,“b”,“c”),从这里:

Map("a"->1, "b"->2, "c"->0)
Map("a"->3, "b"->1, "c"->0)
我需要编写csv:

a,b
1,2
3,1
只有一个collect就可以做到这一点吗?

如果您的声明是:“我的RDD中的每个新元素都可以添加一个我到目前为止还没有见过的新列名”,那么答案显然是无法避免完全扫描。但是您不需要收集驱动程序上的所有元素

您可以使用
aggregate
仅收集列名。此方法包含两个函数,一个是将单个元素插入结果集合,另一个是合并来自两个不同分区的结果

rdd.aggregate(Set.empty[String])( {(s, m) => s union m.keySet }, { (s1, s2) => s1 union s2 })
您将获得RDD中所有列名的集合。在第二次扫描中,您可以打印CSV文件。

如果您的声明是:“我的RDD中的每个新元素都可以添加一个我迄今为止没有见过的新列名”,那么答案显然是无法避免完全扫描。但是您不需要收集驱动程序上的所有元素

您可以使用
aggregate
仅收集列名。此方法包含两个函数,一个是将单个元素插入结果集合,另一个是合并来自两个不同分区的结果

rdd.aggregate(Set.empty[String])( {(s, m) => s union m.keySet }, { (s1, s2) => s1 union s2 })
您将获得RDD中所有列名的集合。在第二次扫描中,您可以打印CSV文件。

如果您的声明是:“我的RDD中的每个新元素都可以添加一个我迄今为止没有见过的新列名”,那么答案显然是无法避免完全扫描。但是您不需要收集驱动程序上的所有元素

您可以使用
aggregate
仅收集列名。此方法包含两个函数,一个是将单个元素插入结果集合,另一个是合并来自两个不同分区的结果

rdd.aggregate(Set.empty[String])( {(s, m) => s union m.keySet }, { (s1, s2) => s1 union s2 })
您将获得RDD中所有列名的集合。在第二次扫描中,您可以打印CSV文件。

如果您的声明是:“我的RDD中的每个新元素都可以添加一个我迄今为止没有见过的新列名”,那么答案显然是无法避免完全扫描。但是您不需要收集驱动程序上的所有元素

您可以使用
aggregate
仅收集列名。此方法包含两个函数,一个是将单个元素插入结果集合,另一个是合并来自两个不同分区的结果

rdd.aggregate(Set.empty[String])( {(s, m) => s union m.keySet }, { (s1, s2) => s1 union s2 })
您将获得RDD中所有列名的集合。在第二次扫描中,您可以打印CSV文件。

Scala和任何其他支持的语言 你可以用

首先,让我们查找所有当前列:

val cols = sc.broadcast(rdd.flatMap(_.keys).distinct().collect())
创建RDD[行]:

val rows = rdd.map {
    row => { Row.fromSeq(cols.value.map { row.getOrElse(_, 0) })}
}
准备架构:

import org.apache.spark.sql.types.{StructType, StructField, IntegerType}

val schema = StructType(
    cols.value.map(field => StructField(field, IntegerType, true)))
将RDD[行]转换为数据帧:

val df = sqlContext.createDataFrame(rows, schema)
写入结果:

// Spark 1.4+, for other versions see spark-csv docs
df.write.format("com.databricks.spark.csv").save("mycsv.csv")
您可以使用其他受支持的语言执行几乎相同的操作

python 如果使用Python且最终数据适合驱动程序内存,则可以通过
toPandas()
方法使用Pandas:

rdd = sc.parallelize([{'a': 1, 'b': 2}, {'b': 1, 'c': 3}])
cols = sc.broadcast(rdd.flatMap(lambda row: row.keys()).distinct().collect())

df = sqlContext.createDataFrame(
    rdd.map(lambda row: {k: row.get(k, 0) for k in cols.value}))

df.toPandas().save('mycsv.csv')
或直接:

import pandas as pd 
pd.DataFrame(rdd.collect()).fillna(0).save('mycsv.csv')
编辑 第二个
收集的一种可能方法是使用累加器构建一组所有列名,或者在找到零的位置对这些列名进行计数,并使用此信息映射行、删除不必要的列或添加零

这是可能的,但效率低下,感觉像作弊。唯一有意义的情况是当零的数量非常少时,但我猜这里不是这样

object ColsSetParam extends AccumulatorParam[Set[String]] {

  def zero(initialValue: Set[String]): Set[String] = {
    Set.empty[String]
  }

  def addInPlace(s1: Set[String], s2: Set[String]): Set[String] = {
    s1 ++ s2
  }
}

val colSetAccum = sc.accumulator(Set.empty[String])(ColsSetParam)
rdd.foreach { colSetAccum += _.keys.toSet } 

Scala和任何其他受支持的语言 你可以用

首先,让我们查找所有当前列:

val cols = sc.broadcast(rdd.flatMap(_.keys).distinct().collect())
创建RDD[行]:

val rows = rdd.map {
    row => { Row.fromSeq(cols.value.map { row.getOrElse(_, 0) })}
}
准备架构:

import org.apache.spark.sql.types.{StructType, StructField, IntegerType}

val schema = StructType(
    cols.value.map(field => StructField(field, IntegerType, true)))
将RDD[行]转换为数据帧:

val df = sqlContext.createDataFrame(rows, schema)
写入结果:

// Spark 1.4+, for other versions see spark-csv docs
df.write.format("com.databricks.spark.csv").save("mycsv.csv")
您可以使用其他受支持的语言执行几乎相同的操作

python 如果使用Python且最终数据适合驱动程序内存,则可以通过
toPandas()
方法使用Pandas:

rdd = sc.parallelize([{'a': 1, 'b': 2}, {'b': 1, 'c': 3}])
cols = sc.broadcast(rdd.flatMap(lambda row: row.keys()).distinct().collect())

df = sqlContext.createDataFrame(
    rdd.map(lambda row: {k: row.get(k, 0) for k in cols.value}))

df.toPandas().save('mycsv.csv')
或直接:

import pandas as pd 
pd.DataFrame(rdd.collect()).fillna(0).save('mycsv.csv')
编辑 第二个
收集的一种可能方法是使用累加器构建一组所有列名,或者在找到零的位置对这些列名进行计数,并使用此信息映射行、删除不必要的列或添加零

这是可能的,但效率低下,感觉像作弊。唯一有意义的情况是当零的数量非常少时,但我猜这里不是这样

object ColsSetParam extends AccumulatorParam[Set[String]] {

  def zero(initialValue: Set[String]): Set[String] = {
    Set.empty[String]
  }

  def addInPlace(s1: Set[String], s2: Set[String]): Set[String] = {
    s1 ++ s2
  }
}

val colSetAccum = sc.accumulator(Set.empty[String])(ColsSetParam)
rdd.foreach { colSetAccum += _.keys.toSet } 

Scala和任何其他受支持的语言 你可以用

首先,让我们查找所有当前列:

val cols = sc.broadcast(rdd.flatMap(_.keys).distinct().collect())
创建RDD[行]:

val rows = rdd.map {
    row => { Row.fromSeq(cols.value.map { row.getOrElse(_, 0) })}
}
准备架构:

import org.apache.spark.sql.types.{StructType, StructField, IntegerType}

val schema = StructType(
    cols.value.map(field => StructField(field, IntegerType, true)))
将RDD[行]转换为数据帧:

val df = sqlContext.createDataFrame(rows, schema)
写入结果:

// Spark 1.4+, for other versions see spark-csv docs
df.write.format("com.databricks.spark.csv").save("mycsv.csv")
您可以使用其他受支持的语言执行几乎相同的操作

python 如果使用Python且最终数据适合驱动程序内存,则可以通过
toPandas()
方法使用Pandas:

rdd = sc.parallelize([{'a': 1, 'b': 2}, {'b': 1, 'c': 3}])
cols = sc.broadcast(rdd.flatMap(lambda row: row.keys()).distinct().collect())

df = sqlContext.createDataFrame(
    rdd.map(lambda row: {k: row.get(k, 0) for k in cols.value}))

df.toPandas().save('mycsv.csv')
或直接:

import pandas as pd 
pd.DataFrame(rdd.collect()).fillna(0).save('mycsv.csv')
编辑 第二个
收集的一种可能方法是使用累加器构建一组所有列名,或者在找到零的位置对这些列名进行计数,并使用此信息映射行、删除不必要的列或添加零

这是可能的,但效率低下,感觉像作弊。唯一有意义的情况是当零的数量非常少时,但我猜这里不是这样

object ColsSetParam extends AccumulatorParam[Set[String]] {

  def zero(initialValue: Set[String]): Set[String] = {
    Set.empty[String]
  }

  def addInPlace(s1: Set[String], s2: Set[String]): Set[String] = {
    s1 ++ s2
  }
}

val colSetAccum = sc.accumulator(Set.empty[String])(ColsSetParam)
rdd.foreach { colSetAccum += _.keys.toSet } 

Scala和任何其他受支持的语言 你可以用

首先,让我们查找所有当前列:

val cols = sc.broadcast(rdd.flatMap(_.keys).distinct().collect())
创建RDD[行]:

val rows = rdd.map {
    row => { Row.fromSeq(cols.value.map { row.getOrElse(_, 0) })}
}
准备架构:

import org.apache.spark.sql.types.{StructType, StructField, IntegerType}

val schema = StructType(
    cols.value.map(field => StructField(field, IntegerType, true)))
转换RDD[行]