blob: 8931591b8df84a8a8d876514e992b59bd9500c04 [file]
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import unittest
from io import StringIO
import numpy as np
import pandas as pd
from pyspark import pandas as ps
from pyspark.testing.pandasutils import PandasOnSparkTestCase
from pyspark.testing.utils import (
have_jinja2,
jinja2_requirement_message,
have_tabulate,
tabulate_requirement_message,
)
# This file contains test cases for 'Serialization / IO / Conversion'
# https://spark.apache.org/docs/latest/api/python/reference/pyspark.pandas/frame.html#serialization-io-conversion
class FrameIOMixin:
@property
def pdf(self):
return pd.DataFrame(
{"a": [1, 2, 3, 4, 5, 6, 7, 8, 9], "b": [4, 5, 6, 3, 2, 1, 0, 0, 0]},
index=np.random.rand(9),
)
@property
def df_pair(self):
pdf = self.pdf
psdf = ps.from_pandas(pdf)
return pdf, psdf
def test_to_numpy(self):
pdf = pd.DataFrame(
{
"a": [4, 2, 3, 4, 8, 6],
"b": [1, 2, 9, 4, 2, 4],
"c": ["one", "three", "six", "seven", "one", "5"],
},
index=np.random.rand(6),
)
psdf = ps.from_pandas(pdf)
self.assert_eq(psdf.to_numpy(), pdf.values)
def test_to_pandas(self):
pdf, psdf = self.df_pair
self.assert_eq(psdf._to_pandas(), pdf)
def test_to_spark(self):
psdf = ps.from_pandas(self.pdf)
with self.assertRaisesRegex(ValueError, "'index_col' cannot be overlapped"):
psdf.to_spark(index_col="a")
with self.assertRaisesRegex(ValueError, "length of index columns.*1.*3"):
psdf.to_spark(index_col=["x", "y", "z"])
@unittest.skipIf(not have_tabulate, tabulate_requirement_message)
def test_to_markdown(self):
pdf = pd.DataFrame(data={"animal_1": ["elk", "pig"], "animal_2": ["dog", "quetzal"]})
psdf = ps.from_pandas(pdf)
self.assert_eq(pdf.to_markdown(), psdf.to_markdown())
def test_from_dict(self):
data = {"row_1": [3, 2, 1, 0], "row_2": [10, 20, 30, 40]}
pdf = pd.DataFrame.from_dict(data)
psdf = ps.DataFrame.from_dict(data)
self.assert_eq(pdf, psdf)
pdf = pd.DataFrame.from_dict(data, dtype="int8")
psdf = ps.DataFrame.from_dict(data, dtype="int8")
self.assert_eq(pdf, psdf)
pdf = pd.DataFrame.from_dict(data, orient="index", columns=["A", "B", "C", "D"])
psdf = ps.DataFrame.from_dict(data, orient="index", columns=["A", "B", "C", "D"])
self.assert_eq(pdf, psdf)
@unittest.skipIf(not have_jinja2, jinja2_requirement_message)
def test_style(self):
# Currently, the `style` function returns a pandas object `Styler` as it is,
# processing only the number of rows declared in `compute.max_rows`.
# So it's a bit vague to test, but we are doing minimal tests instead of not testing at all.
pdf = pd.DataFrame(np.random.randn(10, 4), columns=["A", "B", "C", "D"])
psdf = ps.from_pandas(pdf)
def style_negative(v, props=""):
return props if v < 0 else None
def check_style():
# If the value is negative, the text color will be displayed as red.
pdf_style = pdf.style.map(style_negative, props="color:red;")
psdf_style = psdf.style.map(style_negative, props="color:red;")
# Test whether the same shape as pandas table is created including the color.
self.assert_eq(pdf_style.to_latex(), psdf_style.to_latex())
check_style()
with ps.option_context("compute.max_rows", None):
check_style()
def test_info(self):
pdf, psdf = self.df_pair
pdf_io = StringIO()
psdf_io = StringIO()
psdf.info(buf=psdf_io)
pdf.info(buf=pdf_io, memory_usage=False)
# Split is using to filter out first line with class name
# <class 'pyspark.pandas.frame.DataFrame'> vs <class 'pandas.core.frame.DataFrame'>
self.assert_eq(pdf_io.getvalue().split("\n")[1:], psdf_io.getvalue().split("\n")[1:])
psdf_io.truncate(0)
pdf_io.truncate(0)
psdf.info(buf=psdf_io, max_cols=1)
pdf.info(buf=pdf_io, max_cols=1, memory_usage=False)
self.assert_eq(pdf_io.getvalue().split("\n")[1:], psdf_io.getvalue().split("\n")[1:])
psdf_io.truncate(0)
pdf_io.truncate(0)
psdf.info(buf=psdf_io, show_counts=True)
pdf.info(buf=pdf_io, show_counts=True, memory_usage=False)
self.assert_eq(pdf_io.getvalue().split("\n")[1:], psdf_io.getvalue().split("\n")[1:])
psdf_io.truncate(0)
pdf_io.truncate(0)
psdf.info(buf=psdf_io, show_counts=False)
pdf.info(buf=pdf_io, show_counts=False, memory_usage=False)
self.assert_eq(pdf_io.getvalue().split("\n")[1:], psdf_io.getvalue().split("\n")[1:])
class FrameIOTests(
FrameIOMixin,
PandasOnSparkTestCase,
):
pass
if __name__ == "__main__":
from pyspark.testing import main
main()