【问题标题】:Create a dataframe from pipe delimited text file with no new line character从没有换行符的管道分隔文本文件创建数据框
【发布时间】:2021-10-24 16:23:32
【问题描述】:

我有一个如下的文本文件(.txt 格式)-

|1|NewYork|96|2|Chennai|84|3|Amsterdam|96|

我想使用 pyspark 读取这个数据框,以便创建如下

---------------
c0 | c1| c2
---------------
1 | NewYork|96
---------------
2 | Chennai |84
----------------
3 | Amsterdam |96

基本上我想将每 4 个 pipeline( | ) 分隔符替换为 换行符 (\n)这样我就可以创建数据框了。

谁能帮忙?

【问题讨论】:

    标签: apache-spark pyspark


    【解决方案1】:

    您可以使用此正则表达式 ((?:[^c]*c){n-1}[^c]*)c 匹配每个第 n 个字符,如 here 所示。 (c 代表任何字符)。

    使用上面的正则表达式,我们可以将每第三个 | 替换为 \n(忽略第一个和最后一个 |

    df = spark.read.text("/path/to/file")
    
    # Remove first and last | then replacing every 3rd | with \n
    replaced_df = df.withColumn('value', regexp_replace('value', '^\||\|$', '')) \
         .select(regexp_replace('value','((?:[^\|]*\|){2}[^\|]*)\|','$1\n').alias('value'))
    
    cols = ['c0', 'c1', 'c2']
    
    # Split the column by \n and explode the array column
    replaced_df.select(explode(split('value', '\n'))) \
     .select(split('col','\|').alias('value')) \
     .select(*map(lambda c: col('value').getItem(cols.index(c)).alias(c),cols)).show()
    
    +---+---------+---+
    | c0|       c1| c2|
    +---+---------+---+
    |  1|  NewYork| 96|
    |  2|  Chennai| 84|
    |  3|Amsterdam| 96|
    +---+---------+---+
    

    【讨论】:

      【解决方案2】:

      两种方法解决:

      数据框

      import pyspark.sql.functions as f
      
      df = spark.read.text('/your_data_path/*.txt')
      
      output_df = (df
                   .withColumn('values', f.split(f.expr('substring(`value`, 2, length(`value`) - 2)'), '\|'))
                   .selectExpr('TRANSFORM(SEQUENCE(1, SIZE(values), 3), i -> ' \
                               'STRUCT(values[i - 1] AS c0, values[i] AS c1, values[i + 1] AS c2)) AS values')
                   .selectExpr('inline(values)'))
      
      output_df.show()
      

      RDD

      rdd = sc.textFile('/your_data_path/*.txt')
      
      
      def split(text):
        text = text.strip('|')
        values = text.split('|')
        for i in range(0, len(values), 3):
          yield values[i:i+3]
      
      
      df = (rdd
            .flatMap(split)
            .toDF('c0 string, c1 string, c2 string'))
      
      df.show()
      

      输出

      +---+---------+---+
      | c0|       c1| c2|
      +---+---------+---+
      |  1|  NewYork| 96|
      |  2|  Chennai| 84|
      |  3|Amsterdam| 96|
      +---+---------+---+
      

      【讨论】:

        【解决方案3】:

        一个稍微不同的逻辑,但仍然有效:

        ch="|1|NewYork|96|2|Chennai|84|3|Amsterdam|96|"
        ch=ch[:-1] # You want to delete first |
        ch=ch[1:] # You want to delete last |
        j=0
        cpt=0
        for i in ch:
          if(i=="|"):
            j+=1
          if(j==3): # You replace every third | with \n
            ch=ch[:cpt]+"\n"+ch[cpt+1:]
            j=0
          
          cpt+=1
            
        print(ch)
        
        1|NewYork|96
        2|Chennai|84
        3|Amsterdam|96
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-07-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-20
          • 2023-03-15
          • 1970-01-01
          相关资源
          最近更新 更多