6

Mam ramkę danych df z kolumną VectorUDT o nazwie features. Jak uzyskać element kolumny, powiedzmy pierwszy element?Jak uzyskać dostęp do elementu kolumny VectorUDT w Spark DataFrame?

Próbowałem robić następujące

from pyspark.sql.functions import udf 
first_elem_udf = udf(lambda row: row.values[0]) 
df.select(first_elem_udf(df.features)).show() 

ale pojawia się błąd net.razorvine.pickle.PickleException: expected zero arguments for construction of ClassDict(for numpy.dtype). Ten sam błąd, jeśli zamiast tego wykonam first_elem_udf = first_elem_udf(lambda row: row.toArray()[0]).

Próbowałem również explode(), ale pojawia się błąd, ponieważ wymaga tablicy lub typu mapy.

To powinna być pospolita operacja, jak sądzę.

Odpowiedz

5

wyjście Konwersja do float:

from pyspark.sql.types import DoubleType 
from pyspark.sql.functions import lit, udf 

def ith_(v, i): 
    try: 
     return float(v[i]) 
    except ValueError: 
     return None 

ith = udf(ith_, DoubleType()) 

Przykład użycia:

from pyspark.ml.linalg import Vectors 

df = sc.parallelize([ 
    (1, Vectors.dense([1, 2, 3])), 
    (2, Vectors.sparse(3, [1], [9])) 
]).toDF(["id", "features"]) 

df.select(ith("features", lit(1))).show() 

## +-----------------+ 
## |ith_(features, 1)| 
## +-----------------+ 
## |    2.0| 
## |    9.0| 
## +-----------------+ 

Objaśnienie:

wartości wyjściowe muszą być reserialized na podobne przedmioty Java. Jeśli chcesz uzyskać dostęp do values (strzeżcie SparseVectors) należy użyć item metody:

v.values.item(0) 

które zwracają standardowe skalary Python. Podobnie, jeśli chcesz uzyskać dostęp do wszystkich wartości jako gęstej struktury:

v.toArray().tolist() 
+0

To nie działa dla mnie. – user2205916

+2

@ user2205916 Istnieje tutaj powtarzalny przykład. Chcesz wyjaśnić, co __didn't work__? :) – zero323

+1

To nie działało dla mnie, dopóki nie zmieniłem 'lit (1)' na 'lit (0)' ... co mogłem wywnioskować z twojego odtwarzalnego przykładu. Więc dziękuję! –