web-dev-qa-db-ja.com

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

私は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ファイルは複数の列として。

86
Kernael

すべての行に少なくとも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()
55
G Quintana

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

外部の依存関係を含めずに。

Spark <2.0.0

一般的なケースでは些細なことではない手動解析の代わりに、 spark-csv をお勧めします。

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

ロード、スキーマ推論、不正な行の削除を処理でき、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"))
147
zero323

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)
15
JP Mercier
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())
14
y durga prasad

単純にカンマで分割すると、フィールド内にあるカンマも分割されます(例:a,b,"1,2,3",c)。したがって、お勧めできません。 DataFrames APIを使いたいのであればzero323の答え はいいですが、もしあなたがSparkを使い続けたいのであれば、Pythonでcsvを解析することができます 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パーサーを使用したほうがよいでしょう。

13
Galen Long

さて、一般的なcsvファイルには別のオプションもあります。 https://github.com/seahboonsiew/pyspark-csv 次のように:

次のような文脈があるとします。

sc = SparkContext
sqlCtx = SQLContext or HiveContext

まず、SparkContextを使ってpyspark-csv.pyをexecutorに配布します。

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)
4
optimist

あなたがデータフレームとして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

私にとってはうまくいった。

3
Jeril

これは、 JP Mercierが最初に でPandasを使用することを提案したことと一致していますが、大きな変更があります。つまり、Pandasが実際に1つのピースとして処理し、それを小さいサイズで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()
3
abby sobh

あなたの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
iec2011007

データセット内に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
Yogesh

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)
1
flow2k