9

स्पार्क का स्ट्रिंग इंडेक्सर काफी उपयोगी है, लेकिन जेनरेट किए गए इंडेक्स मानों और मूल तारों के बीच पत्राचार पुनर्प्राप्त करने की आवश्यकता है, और ऐसा लगता है कि पूरा करने के लिए एक अंतर्निहित तरीका होना चाहिए इस। मैं Spark documentation से इस सरल उदाहरण का उपयोग कर उदाहरण देकर स्पष्ट करना होगा:इंडेक्स-स्ट्रिंग पत्राचार स्पार्क स्ट्रिंग इंडेक्सर

from pyspark.ml.feature import StringIndexer 

df = sqlContext.createDataFrame(
    [(0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c")], 
    ["id", "category"]) 
indexer = StringIndexer(inputCol="category", outputCol="categoryIndex") 
indexed_df = indexer.fit(df).transform(df) 

इस सरल मामले हमें देता है:

+---+--------+-------------+ 
| id|category|categoryIndex| 
+---+--------+-------------+ 
| 0|  a|   0.0| 
| 1|  b|   2.0| 
| 2|  c|   1.0| 
| 3|  a|   0.0| 
| 4|  a|   0.0| 
| 5|  c|   1.0| 
+---+--------+-------------+ 

सभी ठीक है और बांका है, लेकिन कई उपयोग के मामलों के लिए मैं के बीच मानचित्रण जानना चाहता हूँ मेरी मूल तार और सूचकांक लेबल।

In [8]: indexed.select('category','categoryIndex').distinct().show() 
+--------+-------------+ 
|category|categoryIndex| 
+--------+-------------+ 
|  b|   2.0| 
|  c|   1.0| 
|  a|   0.0| 
+--------+-------------+ 

जिसके परिणामस्वरूप मैं एक शब्दकोश के रूप में संग्रहीत कर सकती है या इसी तरह अगर मैं चाहता था:

In [12]: mapping = {row.categoryIndex:row.category for row in 
      indexed.select('category','categoryIndex').distinct().collect()} 

In [13]: mapping 
Out[13]: {0.0: u'a', 1.0: u'c', 2.0: u'b'} 

मेरा प्रश्न यह है सबसे आसान तरीका है मुझे लगता है कि कर सकते हैं इस बंद हाथ करने के लिए कुछ इस तरह है : चूंकि यह एक आम काम है, और मैं अनुमान लगा रहा हूं (लेकिन निश्चित रूप से गलत हो सकता है) कि स्ट्रिंग इंडेक्सर किसी भी तरह से इस मैपिंग को संग्रहीत कर रहा है, क्या उपर्युक्त कार्य को और अधिक आसानी से पूरा करने का कोई तरीका है?

मेरा समाधान कम या ज्यादा सरल है, लेकिन बड़ी डेटा संरचनाओं के लिए इसमें अतिरिक्त गणना का एक गुच्छा शामिल है जो (शायद) मैं इससे बच सकता हूं। विचार?

उत्तर

6

लेबल मानचित्रण स्तंभ मेटाडाटा से निकाला जा सकता है:

meta = [ 
    f.metadata for f in indexed_df.schema.fields if f.name == "categoryIndex" 
] 
meta[0] 
## {'ml_attr': {'name': 'category', 'type': 'nominal', 'vals': ['a', 'c', 'b']}} 

जहां ml_attr.vals स्थिति और लेबल के बीच मैपिंग प्रदान:

dict(enumerate(meta[0]["ml_attr"]["vals"])) 
## {0: 'a', 1: 'c', 2: 'b'} 

स्पार्क 1.6+

आप सांख्यिक परिवर्तित कर सकते हैं IndexToString का उपयोग कर लेबल के मान। यह ऊपर दिखाए गए कॉलम मेटाडेटा का उपयोग करेगा।

from pyspark.ml.feature import IndexToString 

idx_to_string = IndexToString(
    inputCol="categoryIndex", outputCol="categoryValue") 

idx_to_string.transform(indexed_df).drop("id").distinct().show() 
## +--------+-------------+-------------+ 
## |category|categoryIndex|categoryValue| 
## +--------+-------------+-------------+ 
## |  b|   2.0|   b| 
## |  a|   0.0|   a| 
## |  c|   1.0|   c| 
## +--------+-------------+-------------+ 

स्पार्क < = 1,5

यह एक गंदा हैक है, लेकिन आप बस एक जावा इंडेक्सर से लेबल निकाल सकते हैं इस प्रकार है:

from pyspark.ml.feature import StringIndexerModel 

# A simple monkey patch so we don't have to _call_java later 
def labels(self): 
    return self._call_java("labels") 

StringIndexerModel.labels = labels 

# Fit indexer model 
indexer = StringIndexer(inputCol="category", outputCol="categoryIndex").fit(df) 

# Extract mapping 
mapping = dict(enumerate(indexer.labels())) 
mapping 
## {0: 'a', 1: 'c', 2: 'b'} 
संबंधित मुद्दे