Spark로 CSV 파일로드


110

저는 Spark를 처음 사용하고 Spark를 사용하여 파일에서 CSV 데이터를 읽으려고합니다. 내가하는 일은 다음과 같습니다.

sc.textFile('file.csv')
    .map(lambda line: (line.split(',')[0], line.split(',')[1]))
    .collect()

이 호출이 내 파일의 첫 번째 두 열 목록을 제공 할 것으로 예상하지만이 오류가 발생합니다.

File "<ipython-input-60-73ea98550983>", line 1, in <lambda>
IndexError: list index out of range

내 CSV 파일이 둘 이상의 열이지만.

답변:


63

모든 행에 2 개 이상의 열이있는 것이 확실 합니까? 확인하기 위해 다음과 같은 것을 시도해 볼 수 있습니까? :

sc.textFile("file.csv") \
    .map(lambda line: line.split(",")) \
    .filter(lambda line: len(line)>1) \
    .map(lambda line: (line[0],line[1])) \
    .collect()

또는 범인 (있는 경우)을 인쇄 할 수 있습니다.

sc.textFile("file.csv") \
    .map(lambda line: line.split(",")) \
    .filter(lambda line: len(line)<=1) \
    .collect()

한 줄에 열이 하나뿐이었습니다. 감사합니다.
Kernael 2015

2
csv모든 이스케이프를 처리하기 위해 내장 라이브러리를 사용하여 구문 분석하는 것이 좋습니다 . 값에 쉼표가있는 경우 단순히 쉼표로 분할하면 작동하지 않기 때문입니다.
sudo

4
구문 분석 CSV로 도구의 많은 바퀴 재발견하지 않는있다
스티븐

2
따옴표 안에 쉼표가 있으면이 코드가 깨집니다. csv 구문 분석은에서 분할하는 것보다 더 복잡 ","합니다.
Alceu Costa

쉼표로 구분됩니다. 이건 정말 나빠.
rjurney

184

Spark 2.0.0 이상

내장 된 csv 데이터 소스를 직접 사용할 수 있습니다.

spark.read.csv(
    "some_input_file.csv", header=True, mode="DROPMALFORMED", schema=schema
)

또는

(spark.read
    .schema(schema)
    .option("header", "true")
    .option("mode", "DROPMALFORMED")
    .csv("some_input_file.csv"))

외부 종속성을 포함하지 않습니다.

스파크 <2.0.0 :

일반적인 경우에는 사소한 것이 아닌 수동 구문 분석 대신 다음을 권장합니다 spark-csv.

확인 스파크 CSV가 경로에 포함되어 있는지 확인 ( --packages, --jars, --driver-class-path)

그리고 다음과 같이 데이터를로드합니다.

(df = sqlContext
    .read.format("com.databricks.spark.csv")
    .option("header", "true")
    .option("inferschema", "true")
    .option("mode", "DROPMALFORMED")
    .load("some_input_file.csv"))

로드, 스키마 추론, 잘못된 라인 삭제를 처리 할 수 ​​있으며 Python에서 JVM으로 데이터를 전달할 필요가 없습니다.

참고 :

스키마를 알고 있다면 스키마 추론을 피하고에 전달하는 것이 DataFrameReader좋습니다. 정수, 이중 및 문자열의 세 열이 있다고 가정합니다.

from pyspark.sql.types import StructType, StructField
from pyspark.sql.types import DoubleType, IntegerType, StringType

schema = StructType([
    StructField("A", IntegerType()),
    StructField("B", DoubleType()),
    StructField("C", StringType())
])

(sqlContext
    .read
    .format("com.databricks.spark.csv")
    .schema(schema)
    .option("header", "true")
    .option("mode", "DROPMALFORMED")
    .load("some_input_file.csv"))

6
이렇게하면 pyspark 셸을 열거 나 spark-submit을 사용할 때 databricks csv 패키지를 포함하는 것을 잊지 마십시오. 예를 들어, pyspark --packages com.databricks:spark-csv_2.11:1.4.0(데이터 브릭 / 스파크 버전을 설치 한 버전으로 변경해야합니다).
Galen Long

pyspark의 csvContext 또는 sqlContext입니까? 스칼라에서는 csvContext가 필요하기 때문에
Geoffrey Anderson

28
from pyspark.sql import SparkSession

spark = SparkSession \
    .builder \
    .appName("Python Spark SQL basic example") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

df = spark.read.csv("/home/stp/test1.csv",header=True,sep="|");

print(df.collect())

다음과 같이 'sep not'separator '를 사용하십시오. df = spark.read.csv ( "/ home / stp / test1.csv", header = True, sep = "|")
Grant Shannon

18

Pandas를 사용하여 CSV 파일을 읽은 다음 Pandas DataFrame을 Spark로 가져 오는 또 다른 옵션입니다.

예를 들면 :

from pyspark import SparkContext
from pyspark.sql import SQLContext
import pandas as pd

sc = SparkContext('local','example')  # if using locally
sql_sc = SQLContext(sc)

pandas_df = pd.read_csv('file.csv')  # assuming the file contains a header
# pandas_df = pd.read_csv('file.csv', names = ['column 1','column 2']) # if no header
s_df = sql_sc.createDataFrame(pandas_df)

7
그는 팬더에서 데이터를로드 할 수 있다면 왜 영업 이익은 스파크에서 수행하고자하는 것
WoodChopper

모든 스파크 클러스터에 대한 종속성을 설치하거나 지정하고 싶지 않습니다 ....
SummerEla

Panda는 읽을 때 파일 청킹을 허용하므로 Pandas가 초기 파일 구문 분석을 처리하도록하는 사용 사례가 여전히 있습니다. 코드는 아래 내 대답을 참조하십시오.
abby sobh

주의 : Pandas는 특히 공백이 포함 된 경우 Spark와 다른 방식으로 열 스키마를 처리합니다. csv를 각 열의 문자열로로드하는 것이 더 안전합니다.
AntiPawn79

@WoodChopper Spark에서 Pandas를 UDF로 사용할 수 있습니다.
flow2k

16

단순히 쉼표로 분할하면 필드 (예 :)에있는 쉼표도 분할 a,b,"1,2,3",c되므로 권장되지 않습니다. DataFrames API를 사용하려는 경우 zero323의 대답 은 좋지만 기본 Spark를 고수하려면 csv 모듈을 사용하여 기본 Python에서 csv를 구문 분석 할 수 있습니다 .

# works for both python 2 and 3
import csv
rdd = sc.textFile("file.csv")
rdd = rdd.mapPartitions(lambda x: csv.reader(x))

편집 : @muon이 주석에서 언급했듯이 이것은 헤더를 다른 행과 같이 취급하므로 수동으로 추출해야합니다. 예를 들어, header = rdd.first(); rdd = rdd.filter(lambda x: x != header)( header필터가 평가되기 전에 수정하지 마십시오 ). 그러나이 시점에서 기본 제공 csv 파서를 사용하는 것이 좋습니다.


1
DataFrames를 사용하기 위해 Hive가 필요하지 않습니다. 솔루션과 관련하여 : a) StringIO. csvb) __next__직접 사용할 수 없으며 빈 줄에서 실패합니다. flatMap을보세요 c) mapPartitions각 행에서 리더를 초기화 하는 대신 사용 하는 것이 훨씬 더 효율적일 것입니다. :)
zero323

수정 해주셔서 감사합니다! 내 대답을 편집하기 전에 완전히 이해했는지 확인하고 싶습니다. 1) 오류가 발생 rdd.mapPartitions(lambda x: csv.reader(x))하는 동안 작동하는 이유는 무엇 rdd.map(lambda x: csv.reader(x))입니까? 나는 둘 다 같은 것을 던질 것으로 예상했다 TypeError: can't pickle _csv.reader objects. 또한 객체에서 mapPartitions"readlines"에 해당하는 일부를 자동으로 호출하는 것 같습니다 csv.reader. 여기서를 사용 하여 .NET 에서 목록을 가져 오기 위해 명시 적으로 map호출해야 __next__했습니다 csv.reader. 2) 어디로 flatMap들어 오나요? mapPartitions혼자 전화하는 것만으로도 효과적이었습니다.
Galen Long

1
rdd.mapPartitions(lambda x: csv.reader(x))개체를 mapPartitions기대 하기 때문에 작동 Iterable합니다. 명시 적으로 표현하고 싶다면 이해하거나 생성자 표현을 할 수 있습니다. map객체를 반복하지 않기 때문에 단독으로는 작동하지 않습니다. 따라서 flatMap(lambda x: csv.reader([x]))독자에게 반복되는 사용 제안 . 그러나 mapPartitions여기가 훨씬 좋습니다.
zero323

1
이것은 헤더가 아니라 데이터 행으로 읽는다는 점에 유의하십시오
muon

7

이것은 PYSPARK에 있습니다.

path="Your file path with file name"

df=spark.read.format("csv").option("header","true").option("inferSchema","true").load(path)

그런 다음 확인할 수 있습니다.

df.show(5)
df.count()

6

csv를 데이터 프레임으로로드하려면 다음을 수행 할 수 있습니다.

from pyspark.sql import SQLContext
sqlContext = SQLContext(sc)

df = sqlContext.read.format('com.databricks.spark.csv') \
    .options(header='true', inferschema='true') \
    .load('sampleFile.csv') # this is your csv file

그것은 나를 위해 잘 작동했습니다.


당신이 마음을 해달라고하면 @GalenLong, 당신은 이미 기존의 답변을 공유 할 수 있습니다
Jeril

이상합니다.이 솔루션에 대한 또 다른 답변이있었습니다. 어쩌면 나는 이것을 다른 질문과 혼동했을 것입니다. 내 잘못이야.
Galen Long

5

이것은 JP Mercier가 처음 에 Pandas 사용에 대해 제안한 것과 일치 하지만 큰 수정 사항이 있습니다. Pandas에 데이터를 청크 단위로 읽으면 더 유연해야합니다. 의미는 Pandas가 실제로 단일 조각으로 처리 할 수있는 것보다 훨씬 큰 파일을 구문 분석하여 더 작은 크기로 Spark에 전달할 수 있다는 의미입니다. (이것은 또한 모든 것을 Pandas에로드 할 수 있다면 Spark를 사용하려는 이유에 대한 의견에 대한 답변이기도합니다.)

from pyspark import SparkContext
from pyspark.sql import SQLContext
import pandas as pd

sc = SparkContext('local','example')  # if using locally
sql_sc = SQLContext(sc)

Spark_Full = sc.emptyRDD()
chunk_100k = pd.read_csv("Your_Data_File.csv", chunksize=100000)
# if you have headers in your csv file:
headers = list(pd.read_csv("Your_Data_File.csv", nrows=0).columns)

for chunky in chunk_100k:
    Spark_Full +=  sc.parallelize(chunky.values.tolist())

YourSparkDataFrame = Spark_Full.toDF(headers)
# if you do not have headers, leave empty instead:
# YourSparkDataFrame = Spark_Full.toDF()
YourSparkDataFrame.show()

5

이제, 모든 일반 csv 파일에 대한 다른 옵션도있다 : https://github.com/seahboonsiew/pyspark-csv 은 다음과 같습니다 :

다음 컨텍스트가 있다고 가정합니다.

sc = SparkContext
sqlCtx = SQLContext or HiveContext

먼저 SparkContext를 사용하여 pyspark-csv.py를 실행자에게 배포합니다.

import pyspark_csv as pycsv
sc.addPyFile('pyspark_csv.py')

SparkContext를 통해 csv 데이터를 읽고 DataFrame으로 변환

plaintext_rdd = sc.textFile('hdfs://x.x.x.x/blah.csv')
dataframe = pycsv.csvToDataFrame(sqlCtx, plaintext_rdd)

3

CSV 데이터가 어떤 필드에도 개행 문자를 포함하지 않는 경우 데이터를로드 textFile()하고 파싱 할 수 있습니다.

import csv
import StringIO

def loadRecord(line):
    input = StringIO.StringIO(line)
    reader = csv.DictReader(input, fieldnames=["name1", "name2"])
    return reader.next()

input = sc.textFile(inputFile).map(loadRecord)

2

데이터 세트에 열 수가 2 개보다 적거나 많은 행이 하나 이상있는 경우이 오류가 발생할 수 있습니다.

나는 또한 Pyspark를 처음 사용하고 CSV 파일을 읽으려고합니다. 다음 코드는 나를 위해 일했습니다.

이 코드에서는 kaggle의 데이터 세트를 사용하고 있습니다. 링크는 다음과 같습니다. https://www.kaggle.com/carrie1/ecommerce-data

1. 스키마를 언급하지 않고 :

from pyspark.sql import SparkSession  
scSpark = SparkSession \
    .builder \
    .appName("Python Spark SQL basic example: Reading CSV file without mentioning schema") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

sdfData = scSpark.read.csv("data.csv", header=True, sep=",")
sdfData.show()

이제 열을 확인하십시오. sdfData.columns

출력은 다음과 같습니다.

['InvoiceNo', 'StockCode','Description','Quantity', 'InvoiceDate', 'CustomerID', 'Country']

각 열의 데이터 유형을 확인하십시오.

sdfData.schema
StructType(List(StructField(InvoiceNo,StringType,true),StructField(StockCode,StringType,true),StructField(Description,StringType,true),StructField(Quantity,StringType,true),StructField(InvoiceDate,StringType,true),StructField(UnitPrice,StringType,true),StructField(CustomerID,StringType,true),StructField(Country,StringType,true)))

그러면 데이터 유형이 StringType 인 모든 열이있는 데이터 프레임이 제공됩니다.

2. 스키마 사용 : 스키마 를 알고 있거나 위 테이블에있는 열의 데이터 유형을 변경하려면 이것을 사용하십시오 (다음 열이 있고 각 열에 대해 특정 데이터 유형을 원한다고 가정합시다).

from pyspark.sql import SparkSession  
from pyspark.sql.types import StructType, StructField
from pyspark.sql.types import DoubleType, IntegerType, StringType
    schema = StructType([\
        StructField("InvoiceNo", IntegerType()),\
        StructField("StockCode", StringType()), \
        StructField("Description", StringType()),\
        StructField("Quantity", IntegerType()),\
        StructField("InvoiceDate", StringType()),\
        StructField("CustomerID", DoubleType()),\
        StructField("Country", StringType())\
    ])

scSpark = SparkSession \
    .builder \
    .appName("Python Spark SQL example: Reading CSV file with schema") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

sdfData = scSpark.read.csv("data.csv", header=True, sep=",", schema=schema)

이제 각 열의 데이터 유형에 대한 스키마를 확인하십시오.

sdfData.schema

StructType(List(StructField(InvoiceNo,IntegerType,true),StructField(StockCode,StringType,true),StructField(Description,StringType,true),StructField(Quantity,IntegerType,true),StructField(InvoiceDate,StringType,true),StructField(CustomerID,DoubleType,true),StructField(Country,StringType,true)))

편집 됨 : 스키마를 명시 적으로 언급하지 않고도 다음 코드 줄을 사용할 수 있습니다.

sdfData = scSpark.read.csv("data.csv", header=True, inferSchema = True)
sdfData.schema

출력은 다음과 같습니다.

StructType(List(StructField(InvoiceNo,StringType,true),StructField(StockCode,StringType,true),StructField(Description,StringType,true),StructField(Quantity,IntegerType,true),StructField(InvoiceDate,StringType,true),StructField(UnitPrice,DoubleType,true),StructField(CustomerID,IntegerType,true),StructField(Country,StringType,true)))

출력은 다음과 같습니다.

sdfData.show()

+---------+---------+--------------------+--------+--------------+----------+-------+
|InvoiceNo|StockCode|         Description|Quantity|   InvoiceDate|CustomerID|Country|
+---------+---------+--------------------+--------+--------------+----------+-------+
|   536365|   85123A|WHITE HANGING HEA...|       6|12/1/2010 8:26|      2.55|  17850|
|   536365|    71053| WHITE METAL LANTERN|       6|12/1/2010 8:26|      3.39|  17850|
|   536365|   84406B|CREAM CUPID HEART...|       8|12/1/2010 8:26|      2.75|  17850|
|   536365|   84029G|KNITTED UNION FLA...|       6|12/1/2010 8:26|      3.39|  17850|
|   536365|   84029E|RED WOOLLY HOTTIE...|       6|12/1/2010 8:26|      3.39|  17850|
|   536365|    22752|SET 7 BABUSHKA NE...|       2|12/1/2010 8:26|      7.65|  17850|
|   536365|    21730|GLASS STAR FROSTE...|       6|12/1/2010 8:26|      4.25|  17850|
|   536366|    22633|HAND WARMER UNION...|       6|12/1/2010 8:28|      1.85|  17850|
|   536366|    22632|HAND WARMER RED P...|       6|12/1/2010 8:28|      1.85|  17850|
|   536367|    84879|ASSORTED COLOUR B...|      32|12/1/2010 8:34|      1.69|  13047|
|   536367|    22745|POPPY'S PLAYHOUSE...|       6|12/1/2010 8:34|       2.1|  13047|
|   536367|    22748|POPPY'S PLAYHOUSE...|       6|12/1/2010 8:34|       2.1|  13047|
|   536367|    22749|FELTCRAFT PRINCES...|       8|12/1/2010 8:34|      3.75|  13047|
|   536367|    22310|IVORY KNITTED MUG...|       6|12/1/2010 8:34|      1.65|  13047|
|   536367|    84969|BOX OF 6 ASSORTED...|       6|12/1/2010 8:34|      4.25|  13047|
|   536367|    22623|BOX OF VINTAGE JI...|       3|12/1/2010 8:34|      4.95|  13047|
|   536367|    22622|BOX OF VINTAGE AL...|       2|12/1/2010 8:34|      9.95|  13047|
|   536367|    21754|HOME BUILDING BLO...|       3|12/1/2010 8:34|      5.95|  13047|
|   536367|    21755|LOVE BUILDING BLO...|       3|12/1/2010 8:34|      5.95|  13047|
|   536367|    21777|RECIPE BOX WITH M...|       4|12/1/2010 8:34|      7.95|  13047|
+---------+---------+--------------------+--------+--------------+----------+-------+
only showing top 20 rows

1

사용하는 경우 spark.read.csv, 나는 옵션을 사용하는 것을 발견 escape='"'하고 multiLine=True받는 가장 일관성있는 솔루션을 제공 CSV 표준을 , 나의 경험, Google 스프레드 시트에서 내 보낸 파일을 CSV와 가장 잘 작동합니다.

그건,

#set inferSchema=False to read everything as string
df = spark.read.csv("myData.csv", escape='"', multiLine=True,
     inferSchema=False, header=True)

불꽃은 어디에서 왔습니까? 맞나요 import pyspark as spark?
Luk Aron

@LukAron pyspark 셸에서 spark이미 초기화되었습니다. 에서 제출 한 스크립트 spark-submit에서 from pyspark.sql import SparkSession; spark = SparkSession.builder.getOrCreate().
flow2k
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.