私は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ファイルは複数の列として。
すべての行に少なくとも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()
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"))
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)
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())
単純にカンマで分割すると、フィールド内にあるカンマも分割されます(例: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パーサーを使用したほうがよいでしょう。
さて、一般的な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)
あなたがデータフレームとして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
私にとってはうまくいった。
これは、 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()
あなたの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より少ないまたは多い列数を持つ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
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)