SparkでCSVファイルを読み込む


110

Sparkを初めて使用し、SparkでファイルからCSVデータを読み取ろうとしています。これが私がやっていることです:

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

この呼び出しでファイルの最初の2列のリストが表示されると思いますが、次のエラーが発生します。

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

以上で、1行1列のみでした。ありがとうございました。
カーナエル2015

2
組み込みcsvライブラリを使用して解析してすべてのエスケープを処理することをお勧めします。たとえば、値にカンマがある場合、カンマによる単純な分割は機能しません。
sudo 2017

4
csvを解析するツールはたくさんあります。車輪を再発明しないでください
Stephen

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。整数、倍精度、文字列の3つの列があると仮定します。

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(databricks / sparkのバージョンを、インストールしたバージョンに必ず変更してください)。
Galen Long

それはpysparkのcsvContextまたは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」を使用します。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
OPがパンダにデータをロードできるのに、なぜOPはスパークを実行したいのですか
WoodChopper 2015年

すべてのスパーククラスターに依存関係をインストールまたは指定したくない...
SummerEla

Pandaでは、ファイルの読み取り時にチャンクを許可しているため、Pandaに初期ファイル解析を処理させるためのユースケースがまだあります。コードについては、以下の私の答えを参照してください。
abby sobh 2016年

注意:特に空白が含まれる場合、パンダはスパークとは異なる方法で列スキーマを処理します。各列の文字列としてcsvをロードする方が安全です。
AntiPawn79 2017

@WoodChopper PandasをSparkのUDFとして使用できますか?
flow2k

16

単にカンマで分割するとa,b,"1,2,3",c、フィールド内のカンマも分割されるため(例:)、推奨されません。DataFrames APIを使用したい場合はzero323の答えが適切ですが、ベースのSparkに固執したい場合は、csvモジュールを使用してベースPythonで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フィルターが評価される前に変更しないでください)。しかし、現時点では、組み込みのcsvパーサーを使用する方がよいでしょう。


1
DataFrameを使用するためにHiveは必要ありません。ソリューションについて:a)は必要ありませんStringIOcsvイテラブルを使用できますb)__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。またmapPartitionscsv.readerオブジェクトの「readlines」に相当するものを自動的に呼び出すようにも見えますが、では、リストをから取り出すために明示的に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に小さなサイズで渡すことができます。(これは、とにかくすべてをパンダにロードできるのであればなぜ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未満または複数の列を持つ1つ以上の行がある場合、このエラーが発生する可能性があります。

私は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.