Как мне прочитать нестандартный CSV-файл в dataframe с python или scala - PullRequest
3 голосов
/ 24 января 2020

У меня есть выборка набора данных ниже для обработки с помощью python или scala:

FWD,13032009:09:01,10.56| FWD,13032009:10:53,11.23| FWD,13032009:15:40,23.20
SPOT,13032009:09:04,11.56| FWD,13032009:11:45,11.23| SPOT,13032009:12:30,23.20
FWD,13032009:08:01,10.56| SPOT,13032009:12:30,11.23| FWD,13032009:13:20,23.20| FWD,13032009:14:340,56.00
FWD,13032009:08:01,10.56| SPOT,13032009:12:30,11.23| FWD,13032009:13:20,23.20

Каждая строка должна быть разбита на несколько меньших строк, которые могут быть дополнительно разбиты.

То, что я ищу, - это эффективный способ создания RDD или Dataframe с содержанием ниже:

FWD,13032009:09:01,10.56 
FWD,13032009:10:53,11.23
FWD,13032009:15:40,23.20
SPOT,13032009:09:04,11.56
FWD,13032009:11:45,11.23
SPOT,13032009:12:30,23.20
FWD,13032009:08:01,10.56
SPOT,13032009:12:30,11.23
FWD,13032009:13:20,23.20
FWD,13032009:14:340,56.00
FWD,13032009:08:01,10.56
SPOT,13032009:12:30,11.23
FWD,13032009:13:20,23.20

Обратите внимание: чем эффективнее, тем лучше, так как общее количество строк в производстве может достигать миллиона

Большое спасибо.

Ответы [ 3 ]

0 голосов
/ 24 января 2020

Предполагая, что вы читаете из файла CSV, вы можете прочитать каждую строку в список. Сгладьте значения и затем обработайте их как отдельные строки.

Считайте файл в список - 1 миллион строк не должен быть слишком большим для обработки:

import csv
import itertools

import pandas as pd

with open('test.csv','r') as f:
    reader = csv.reader(f, delimiter = '|')
    rows = list(reader)

Сведение и разделение из одного списка - превосходная библиотека itertools из стандартной библиотеки Python возвращает генератор, который помогает с памятью и эффективен.

flat_rows = itertools.chain.from_iterable(rows)
list_rows = [i.strip().split(',') for i in flat_rows]

Вложенный список , list_rows теперь дает чистый и отформатированный список, который вы можете отправить на pandas, если хотите создать dataframe.

list_rows
>>
[['FWD', '13032009:09:01', '10.56'],
 ['FWD', '13032009:10:53', '11.23'],
 ['FWD', '13032009:15:40', '23.20'],
 ['SPOT', '13032009:09:04', '11.56'],
 ['FWD', '13032009:11:45', '11.23'],
 ['SPOT', '13032009:12:30', '23.20'],
 ['FWD', '13032009:08:01', '10.56'],
 ['SPOT', '13032009:12:30', '11.23'],
 ['FWD', '13032009:13:20', '23.20'],
 ['FWD', '13032009:14:340', '56.00'],
 ['FWD', '13032009:08:01', '10.56'],
 ['SPOT', '13032009:12:30', '11.23'],
 ['FWD', '13032009:13:20', '23.20']]

df = pd.DataFrame(list_rows)
0 голосов
/ 24 января 2020

Вот способ Scala, если вы заинтересованы,

val rdd1 = sc.parallelize(List("FWD,13032009:09:01,10.56| FWD,13032009:10:53,11.23| FWD,13032009:15:40,23.20", "SPOT,13032009:09:04,11.56| FWD,13032009:11:45,11.23| SPOT,13032009:12:30,23.20","FWD,13032009:08:01,10.56| SPOT,13032009:12:30,11.23| FWD,13032009:13:20,23.20| FWD,13032009:14:340,56.00","FWD,13032009:08:01,10.56| SPOT,13032009:12:30,11.23| FWD,13032009:13:20,23.20"))

val rdd2 = rdd1.flatMap(l => l.replaceAll(" ","").split("\\|")) val rds = rdd2.toDS

val df = spark.read.csv(rds)

df.show(false) +----+---------------+-----+ |_c0 |_c1 |_c2 | +----+---------------+-----+ |FWD |13032009:09:01 |10.56| |FWD |13032009:10:53 |11.23| |FWD |13032009:15:40 |23.20| |SPOT|13032009:09:04 |11.56| |FWD |13032009:11:45 |11.23| |SPOT|13032009:12:30 |23.20| |FWD |13032009:08:01 |10.56| |SPOT|13032009:12:30 |11.23| |FWD |13032009:13:20 |23.20| |FWD |13032009:14:340|56.00| |FWD |13032009:08:01 |10.56| |SPOT|13032009:12:30 |11.23| |FWD |13032009:13:20 |23.20| +----+---------------+-----+

0 голосов
/ 24 января 2020

Python решение: если вы получите текст в виде строки, вы можете replace() свою | последовательность с новой строкой (\n) и затем прочитать ее как DataFrame:

import pandas as pd
from io import StringIO

data_set = """FWD,13032009:09:01,10.56| FWD,13032009:10:53,11.23| FWD,13032009:15:40,23.20
SPOT,13032009:09:04,11.56| FWD,13032009:11:45,11.23| SPOT,13032009:12:30,23.20
FWD,13032009:08:01,10.56| SPOT,13032009:12:30,11.23| FWD,13032009:13:20,23.20| FWD,13032009:14:340,56.00
FWD,13032009:08:01,10.56| SPOT,13032009:12:30,11.23| FWD,13032009:13:20,23.20
"""
data_set *= 100000  # Make it over a million elements to ensure performance is adequate
data_set = data_set.replace("| ", "\n")

data_set_stream = StringIO(data_set)  # Pandas needs to read a file-like object, so need to turn our string into a buffer
df = pd.read_csv(data_set_stream)
print(df)  # df is our desired DataFrame
...