स्पार्क के साथ CSV फ़ाइल लोड करें


110

मैं स्पार्क के लिए नया हूं और मैं स्पार्क के साथ एक फाइल से सीएसवी डेटा को पढ़ने की कोशिश कर रहा हूं। यहाँ मैं क्या कर रहा हूँ:

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()

वह यह था, केवल एक कॉलम के साथ एक पंक्ति, धन्यवाद।
कर्नेल

2
यह बेहतर है कि बिल्ट-इन csvलाइब्रेरी का उपयोग करके सभी भागने से बचें क्योंकि अल्पविराम से विभाजित करने से काम नहीं चलेगा, यदि कहें, मानों में अल्पविराम हैं।
सूडो

4
सीएसवी को पार्स करने के लिए बहुत सारे उपकरण हैं, पहिया को
स्टीफन

2
यदि उद्धरण के अंदर अल्पविराम है तो यह कोड टूट जाएगा। पार्सिंग सीएसवी बस में विभाजित होने की तुलना में अधिक जटिल है ","
अलसी कोस्टा जूल

यह अल्पविराम के लिए टूट जाता है। यह बहुत बुरा है।
rjurney

184

स्पार्क 2.0.0+

आप अंतर्निहित सीएसवी डेटा स्रोत का सीधे उपयोग कर सकते हैं:

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:

सुनिश्चित करें कि स्पार्क सीएसवी पथ में शामिल किया गया है ( --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"))

यह लोडिंग, स्कीमा इंफ़ेक्शन, ख़राब लाइनों को छोड़ना और पायथन से जेवीएम तक डेटा पारित करने की आवश्यकता नहीं है।

नोट :

यदि आप स्कीमा को जानते हैं, तो स्कीमा की रोकथाम से बचना और इसे पास करना बेहतर है 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 खोल खोलते हैं या स्पार्क-सबमिट का उपयोग करते हैं, तो databricks csv पैकेज को शामिल करना न भूलें। उदाहरण के लिए, pyspark --packages com.databricks:spark-csv_2.11:1.4.0(अपने द्वारा इंस्टॉल किए गए डेटाट्रीक / स्पार्क संस्करणों को बदलना सुनिश्चित करें)।
गैलन लॉन्ग

क्या यह csvContext या pyspark में sqlContext है? क्योंकि scala में आपको 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' 'विभाजक' को निम्नानुसार उपयोग करें: df = spark.read.csv ("/ home / stp / test1.csv", शीर्ष लेख = True, sep = "")
अनुदान शैनन

18

और फिर भी एक और विकल्प जो पंडों का उपयोग करके सीएसवी फ़ाइल को पढ़ने और फिर स्पार्क में पंडों के डेटाफ़्रेम को आयात करने से संबंधित है।

उदाहरण के लिए:

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
अगर वह पंडों में डेटा लोड करने में सक्षम है तो ओपी चिंगारी पर क्यों करना चाहेगा
वुडकॉपर

हर स्पार्क क्लस्टर पर निर्भरता स्थापित करने या निर्दिष्ट करने के लिए नहीं चाहिए ....
समरएला

पांडा पढ़ने की अनुमति देता है जब पंडों को प्रारंभिक फ़ाइल पार्सिंग को संभालने के लिए यहां उपयोग-मामला होता है, इसलिए पढ़ने के दौरान फ़ाइल को चैंकाने की अनुमति देता है। कोड के लिए नीचे मेरा जवाब देखें।
अब्बी सोब

सावधानी: पंडों ने कॉलम स्कीमा को स्पार्क की तुलना में अलग-अलग तरीके से हैंडल किया है, खासकर जब रिक्त स्थान शामिल होते हैं। प्रत्येक स्तंभ के लिए स्ट्रिंग के रूप में सीएसवी लोड करने के लिए सुरक्षित है।
एंटीपॉन79

@WoodChopper आप स्पार्क में यूडीएफ के रूप में पंडों का उपयोग कर सकते हैं, नहीं?
flow2k

16

बस अल्पविराम से विभाजित करने से उन अल्पविरामों को भी विभाजित किया जाएगा जो खेतों (जैसे a,b,"1,2,3",c) के भीतर हैं , इसलिए यह अनुशंसित नहीं है। यदि आप DataFrames API का उपयोग करना चाहते हैं, तो शून्य 323 का उत्तर अच्छा है, लेकिन यदि आप आधार स्पार्क से चिपके रहना चाहते हैं, तो आप csv मॉड्यूल के साथ बेस पायथन में csvs को पार्स कर सकते हैं :

# 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कि फ़िल्टर का मूल्यांकन करने से पहले संशोधित न करें )। लेकिन इस बिंदु पर, आप शायद बिल्ट-इन सीएसवी पार्सर का उपयोग कर रहे हैं।


1
आपको DataFrames का उपयोग करने के लिए Hive की आवश्यकता नहीं है। आपके समाधान के बारे में: क) इसकी कोई आवश्यकता नहीं है StringIOcsvकिसी भी iterable b का उपयोग कर सकते हैं) __next__सीधे इस्तेमाल नहीं किया जाना चाहिए और खाली लाइन पर विफल हो जाएगा। फ्लैटपाइप c पर एक नज़र डालें) यह mapPartitionsप्रत्येक पंक्ति पर रीडर को इनिशियलाइज़ करने के बजाय उपयोग करने के लिए अधिक कुशल होगा :)
शून्य 323

सुधार के लिए बहुत बहुत धन्यवाद! इससे पहले कि मैं अपना उत्तर संपादित करूं, मैं यह सुनिश्चित करना चाहता हूं कि मैं पूरी तरह से समझूं। 1) एक त्रुटि rdd.mapPartitions(lambda x: csv.reader(x))को rdd.map(lambda x: csv.reader(x))फेंकते समय काम क्यों करता है ? मुझे उम्मीद थी कि दोनों समान फेंक देंगे TypeError: can't pickle _csv.reader objects। ऐसा भी लगता है mapPartitionsकि csv.readerऑब्जेक्ट पर "रीडलाइन" के बराबर स्वचालित रूप से कॉल करता है, जहां map, मुझे __next__सूची से बाहर निकलने के लिए स्पष्ट रूप से कॉल करने की आवश्यकता है csv.reader। 2) कहां flatMapआता है? बस फोन mapPartitionsकरना मेरे लिए काम कर गया।
गेलन लांग

1
rdd.mapPartitions(lambda x: csv.reader(x))काम करता है क्योंकि mapPartitionsएक Iterableवस्तु की उम्मीद है । यदि आप स्पष्ट होना चाहते हैं तो आप समझ या जनरेटर की अभिव्यक्ति कर सकते हैं। mapअकेले काम नहीं करता है क्योंकि यह वस्तु पर पुनरावृति नहीं करता है। इसलिए मेरे सुझाव का उपयोग करने के लिए flatMap(lambda x: csv.reader([x]))जो पाठक पर पुनरावृत्ति करेगा। लेकिन mapPartitionsयहां बहुत बेहतर है।
432

1
ध्यान दें कि यह हेडर को डेटा की एक पंक्ति के रूप में पढ़ा जाएगा, हेडर के रूप में नहीं
म्यूऑन

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 अगर आपको कोई आपत्ति नहीं है, तो क्या आप पहले से मौजूद जवाब
जेरिल

अजीब, मैं कसम खाता हूँ कि इस समाधान के साथ एक और जवाब था। शायद मैं एक और सवाल के साथ यह भ्रमित हो गया। मेरी गलती।
गेलन लॉन्ग

5

जेपी मर्सियर ने शुरू में पंडों के इस्तेमाल के बारे में क्या सुझाव दिया था, यह इन-लाइन है , लेकिन एक बड़े संशोधन के साथ: यदि आप पंडों के डेटा को चंक्स में पढ़ते हैं, तो यह अधिक निंदनीय होना चाहिए। मतलब, कि आप पंडों की तुलना में बहुत बड़ी फ़ाइल को पार्स कर सकते हैं, वास्तव में एक ही टुकड़े के रूप में संभाल सकते हैं और इसे छोटे आकार में स्पार्क को पास कर सकते हैं। (यह इस बारे में टिप्पणी का भी जवाब देता है कि स्पार्क का उपयोग क्यों करना चाहते हैं यदि वे पंडों को किसी भी तरह से लोड कर सकते हैं।)

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

अब, किसी भी सामान्य सीएसवी फ़ाइल के लिए एक और विकल्प भी है: 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 के माध्यम से सीएसवी डेटा पढ़ें और इसे डेटाफ़्रेम में कनवर्ट करें

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

3

यदि आपका सीएसवी डेटा किसी भी क्षेत्र में नई सीमा नहीं रखता है, तो आप अपना डेटा लोड कर सकते हैं 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)))

यह डेटा कॉलम को स्ट्रांगटाइप के रूप में डेटाटाइप के साथ सभी कॉलम देगा

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='"'और CSV मानक केmultiLine=True लिए सबसे सुसंगत समाधान प्रदान करते हैं , और मेरे अनुभव में 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?
लुक एरन

@LukAron एक पिसपार्क शेल में, sparkपहले से ही आरंभिक है। द्वारा प्रस्तुत स्क्रिप्ट में spark-submit, आप इसे तुरंत लिख सकते हैं from pyspark.sql import SparkSession; spark = SparkSession.builder.getOrCreate()
1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.