pyspark用字符串中的空格拆分csv - jupyter notebook

时间:2017-12-08 22:13:48

标签: python regex pyspark spark-dataframe

我不想阅读文本文件,我想对现有Dataframe

执行操作

我的DataFrame只有一个列文本,例如文件," tabSeparator"

这是结构化文件,有3列,分隔符标签。 如果具有嵌入的标签,则会用双引号括起来( var nodes = Array.prototype.slice.call(element.childNodes, 0); ko.utils.arrayForEach(nodes, function (node) { if (node && node.nodeType !== 1) { node.parentNode.removeChild(node); } }); return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); }

示例:

"xxx xx"

我正在使用正则表达式: 我正在使用 pyspark Jupyter笔记本

-------------------------
col_0
-------------------------
c11   c12    c13
c21 c22 c23   
"c 31" "c 32" c33

不确定问题是使用正则表达式还是解析文件的方法,但我无法创建一个新的DataFrame,解析了3列,结果

myre = '([\\t ]?(\\".*?\\"|[^\\t ]+))'

df = textDF.withColumn("tmp", split( col("_c0"), myre))\
      .select(\
        col("tmp").getItem(0).alias("col_1"),\
        col("tmp").getItem(1).alias("col_2"),\
        col("tmp").getItem(2).alias("col_3")
      )

2 个答案:

答案 0 :(得分:0)

这不是csv读者无法处理的:

spark.read.option("delimiter", "\t").csv(path_to_file)

在Spark 2.3中,您可以在现有的分布式数据结构上完成:

df = spark.createDataFrame([
    'c11\tc12\tc13', 'c21\tc22\tc23', '"c\t31"\t"c\t32"\t"c\t33"'
], "string").toDF("col_0")


spark.read.option('delimiter', '\t').csv(df.rdd.map(lambda x: x.col_0)).show()


# +----+----+----+
# | _c0| _c1| _c2|
# +----+----+----+
# | c11| c12| c13|
# | c21| c22| c23|
# |c    31|c    32|c    33|
# +----+----+----+

使用csv的UDF可能在2.2中使用Python 3,但速度很慢:

from pyspark.sql.functions import udf
import csv

@udf("struct<c0:string,c1:string,c2:string>")
def csv_(s):
    try:
        return next(csv.reader([s], delimiter="\t"))
    except: pass

df.select(csv_("col_0").alias("tmp")).select("tmp.*").show()

# +----+----+----+
# |  c0|  c1|  c2|
# +----+----+----+
# | c11| c12| c13|
# | c21| c22| c23|
# |c    31|c    32|c    33|
# +----+----+----+

答案 1 :(得分:-1)

显然你遇到的问题是有两种可能的分隔符。

使用DataFrames加载只有一个分隔符的文件非常简单,例如制表符分隔符,它们被视为CSV文件,但它不是逗号,而只是一个标签。

在这种特殊情况下,您可以这样阅读:

yourDF = spark.read.option(&#34;分隔符&#34;,&#34; \ t&#34;)。csv(&#39; / tabSeparator /&#39;)

但如果你有多个,我相信唯一的选择是使用正则表达式。您也可以使用RDD并编写更长的函数并使用map。