Как гомогонизировать данные в фрейме данных Pyspark spark.sql - PullRequest
0 голосов
/ 11 апреля 2019

Я скачал 1,9 ГБ CSV-файл, содержащий данные AirBnB. Хотя все столбцы имеют тип данных «строка», у меня есть несколько столбцов, которые не являются «однородными», например столбец «Удобства», где некоторые записи имеют количество удобств в данном конкретном свойстве, а другие имеют список удобств. Все в строковом формате.

Итак, вот что у меня есть:

from pyspark import SparkContext, SparkConf
import pandas as pd
import numpy as np
conf = SparkConf().setAppName("app")
sc = SparkContext(conf=conf)

from pyspark.sql import SQLContext
SQLCtx = SQLContext(sc)

air =SQLCtx.read.load('/home/john/Downloads/airbnb-listings.csv',
                             format = "com.databricks.spark.csv",
                             header = "true",
                             sep = ";",
                             inferSchema = "true")

#check for missing values
from pyspark.sql.functions import col,sum
air.select(*(sum(col(c).isNull().cast("int")).alias(c) for c in air.columns)).show()

Итак, после удаления нескольких столбцов и удаления пропущенных значений, у меня есть это:

Keep = ['Price', 'Bathrooms', 'Bedrooms', 'Beds', 'Bed Type', 'Amenities',
       'Security Deposit', 'Cleaning Fee', 'Guests Included', 'Extra People',
       'Review Scores Rating', 'Cancellation Policy','Host Response Rate', 
       'Country Code', 'Zipcode']

data = air.select(*Keep)
reduced2 = data.na.drop()

#final shape after dropping missing values.
print((reduced2.count(), len(reduced2.columns)))

Я могу преобразовать несколько строк в кадр данных панд:

df3 = pd.DataFrame(reduced2.take(50), columns = reduced2.columns)

Небольшая часть списка "Удобства":

Wireless Internet,Air conditioning,Kitchen,Fre...
2                                                    10
3     Internet,Wireless Internet,Air conditioning,Ki...
4     TV,Cable TV,Internet,Wireless Internet,Air con...
5     TV,Wireless Internet,Air conditioning,Pool,Kit...
6     TV,Wireless Internet,Air conditioning,Pool,Kit...
7     Internet,Wireless Internet,Kitchen,Free parkin...
8     TV,Wireless Internet,Air conditioning,Pool,Kit...
9     Wireless Internet,Air conditioning,Kitchen,Fre...
10    TV,Cable TV,Internet,Wireless Internet,Air con...
14                                                   10
16                                                   10
17    TV,Internet,Wireless Internet,Air conditioning...
18    TV,Cable TV,Internet,Wireless Internet,Air con...
19    TV,Internet,Wireless Internet,Air conditioning...
20    TV,Wireless Internet,Air conditioning,Pool,Kit...
23    TV,Cable TV,Internet,Wireless Internet,Air con...
28                                                    9
33                                                   10
34    Internet,Wireless Internet,Kitchen,Elevator in...
37                                                   10

Как видите, у меня будут проблемы с этим, как есть. Я могу сделать что-то в обычных пандах достаточно легко, чтобы это исправить, например:

for i in range(len(df3['Amenities'])):
    if len(df3["Amenities"][i])>2:
        df3['Amenities'][i] = str(len(df3['Amenities'][i].split(',')))

Теперь я понимаю, что, возможно, это не самый хороший способ сделать это, но он превращает все, что в списке, в число. Мне нужен способ сделать что-то подобное для столбца в кадре данных SQL pyspark, если это вообще возможно.

Спасибо!

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Если я вас правильно понял, вы хотите рассчитать количество элементов, разделенных ,, но при этом оставьте строки, которые уже являются числами. если это так, вы можете попробовать следующее:

from pyspark.sql import functions as F

df.withColumn('Amenities'
    , F.when(df.Amenities.rlike('^\d+$'), df.Amenities) \
       .otherwise(F.size(F.split('Amenities', ","))) \
       .astype("string")
).show()  

Так, если в столбцах Aferences задано целое число df.Amenities.rlike('^\d+$'), мы будем сохранять его как df.Amenities, в противном случае, используйте F.size() и F.split() для вычисления количества элементов. затем преобразовать результат в «строку»

0 голосов
/ 11 апреля 2019

Я не знаком с PySpark SQL Dataframes, только ванильные панды.

Не уверен, какова ваша задача, но, возможно, стоит рассмотреть возможность превращения этого столбца в два столбца.Например (при условии, что это возможно в PySpark):

df['Amenities_count'] = pd.to_numeric(df['Amenities'], errors='coerce')
mask_entries_with_list = df['Amenities_count'].isna()
mask_entries_with_number = ~mask_entries_with_list
df.loc[mask_entries_with_number, 'Amenities'] = []
df.loc[mask_entries_with_list, 'Amenities_count'] = df['Amenities'].apply(len)

(не проверено)

...