देशी अजगर प्रकार सुन्न dtypes परिवर्तित


238

अगर मेरे पास एक सुस्पष्ट dtype है, तो मैं इसे अपने निकटतम अजगर डेटा प्रकार में स्वचालित रूप से कैसे परिवर्तित करूं? उदाहरण के लिए,

numpy.float32 -> "python float"
numpy.float64 -> "python float"
numpy.uint32  -> "python int"
numpy.int16   -> "python int"

मैं इन सभी मामलों की मैपिंग के साथ आने की कोशिश कर सकता था, लेकिन क्या खसखस ​​अपने dtypes को निकटतम संभावित देशी अजगर प्रकारों में परिवर्तित करने के कुछ स्वचालित तरीके प्रदान करता है? इस मानचित्रण को संपूर्ण होने की आवश्यकता नहीं है, लेकिन इसे सामान्य dtypes में बदलना चाहिए, जिसमें एक करीबी अजगर एनालॉग है। मुझे लगता है कि यह पहले से ही सुन्न में कहीं होता है।

जवाबों:


325

val.item()एक देशी पायथन प्रकार के अधिकांश न्यूपे वैल्यू को बदलने के लिए उपयोग करें :

import numpy as np

# for example, numpy.float32 -> python float
val = np.float32(0)
pyval = val.item()
print(type(pyval))         # <class 'float'>

# and similar...
type(np.float64(0).item()) # <class 'float'>
type(np.uint32(0).item())  # <class 'long'>
type(np.int16(0).item())   # <class 'int'>
type(np.cfloat(0).item())  # <class 'complex'>
type(np.datetime64(0, 'D').item())  # <class 'datetime.date'>
type(np.datetime64('2001-01-01 00:00:00').item())  # <class 'datetime.datetime'>
type(np.timedelta64(0, 'D').item()) # <class 'datetime.timedelta'>
...

(एक अन्य विधि है np.asscalar(val), हालांकि यह NumPy 1.16 के बाद से पदावनत है)।


जिज्ञासु के लिए, आपके सिस्टम के लिए NumPy सरणी स्केलरों के रूपांतरणों की एक तालिका बनाने के लिए:

for name in dir(np):
    obj = getattr(np, name)
    if hasattr(obj, 'dtype'):
        try:
            if 'time' in name:
                npn = obj(0, 'D')
            else:
                npn = obj(0)
            nat = npn.item()
            print('{0} ({1!r}) -> {2}'.format(name, npn.dtype.char, type(nat)))
        except:
            pass

कुछ NumPy प्रकार है कि सहित कुछ सिस्टम, पर कोई देशी अजगर बराबर हैं: clongdouble, clongfloat, complex192, complex256, float128, longcomplex, longdoubleऔर longfloat। उपयोग करने से पहले इन्हें अपने निकटतम न्यूमपी समकक्ष में परिवर्तित करना होगा .item()


मैं पांडा (0.23.0) का उपयोग कर रहा हूं। कम से कम उस संस्करण के लिए, np.str में .item () विधि नहीं है इसलिए मैंने देखा कि एक कोशिश ब्लॉक के अंदर .item () को लपेटने का एकमात्र तरीका था।
रॉबर्ट लुग

3
@RobertLugg np.strएक Numpy प्रकार नहीं है, यानी np.str is str, इसलिए यह सिर्फ एक मानक पायथन प्रकार का उपनाम है। के साथ भी यही np.float, np.int, np.bool, np.complex, और np.object। Numpy प्रकार में एक अनुगामी होता है _, उदा np.str_
टी

मै समझता हुँ। तो मुद्दा यह है "यह अच्छा होगा अगर" मैं कर सकता था: np.float64(0).item()और भी np.float(0).item()। दूसरे शब्दों में, उन मामलों के लिए जहां यह पता है कि क्या करना है, .item()भले ही यह समान मूल्य लौटाए, भले ही विधि का समर्थन करें । इस तरह से मैं .item()विशेष आवरण के बिना कहीं अधिक खस्ता खोपड़ी पर आवेदन कर सकता था । जैसा कि यह है, अंतर्निहित कार्यान्वयन के कारण प्रतीत होता है समानांतर अवधारणाएं भिन्न हैं। मैं पूरी तरह से समझता हूं कि ऐसा क्यों किया गया था। लेकिन यह पुस्तकालय उपयोगकर्ता के लिए एक झुंझलाहट है।
रॉबर्ट लैग

45

खुद को मिश्रित प्रकार और मानक अजगर के मिश्रित समूह में पाया। जैसा कि सभी संख्यात्मक प्रकार से प्राप्त होते हैं numpy.generic, यहां बताया गया है कि आप सब कुछ अजगर मानक प्रकारों में कैसे बदल सकते हैं:

if isinstance(obj, numpy.generic):
    return numpy.asscalar(obj)

5
स्वीकार किए गए उत्तर नोटों के रूप में , NumPy 1.16 ने np.asscalar()विधि को पदावनत कर दिया । क्यों? संभवतः बिना किसी अच्छे कारण के। एक दशक के सापेक्ष स्थिरता के बावजूद, NumPy API अब एक अस्थिर चलती लक्ष्य है जो डाउनस्ट्रीम अनुप्रयोगों से निरंतर रखरखाव को अनिवार्य करता है। कम से कम उन्होंने हमें अभी के लिएitem() ... विधि छोड़ दी
सेसिल करी

asscalar विधि numpy के v1.6 के बाद से मूल्यह्रास हुआ है
इस्वर

आप उत्तर को आसानी से बदल सकते हैं if isinstance(o, numpy.generic): return o.item() raise TypeErrorऔर यह फिर से गैर-हटाए गए उत्तर में बदल जाता है: D
Buggy

19

यदि आप कनवर्ट करना चाहते हैं (numpy.array या numpy स्केलर या देशी प्रकार या numpy.darray) तो देशी प्रकार के लिए आप बस कर सकते हैं:

converted_value = getattr(value, "tolist", lambda: value)()

सूची अपने स्केलर या सरणी को अजगर मूल प्रकार में बदल देगा। डिफ़ॉल्ट लैम्ब्डा फ़ंक्शन उस मामले का ध्यान रखता है जहां मूल्य पहले से ही मूल है।


2
मिश्रित प्रकार (देशी और गैर-देशी) के लिए सबसे साफ दृष्टिकोण, अच्छी तरह से किया गया! और उन लोगों के लिए जो आश्चर्य की बात है, हाँ, एक सूची केवल एक मान (स्केलर) लौटाती है जब आप इसे एक ही मूल्य पर बुला रहे हैं, न कि एक सूची जैसा कि आप सोच सकते हैं। ध्यान देने योग्य बात यह है कि लंबोदर लिखने का सरल तरीका है lambda: valueक्योंकि हम कोई इनपुट नहीं चाहते हैं।
fgblomqvist

getattr+ tolistकॉम्बो न केवल सार्वभौमिक है, बल्कि सदिश भी है! (अनलिंक .item ())
mirekphd

11

कैसा रहेगा:

In [51]: dict([(d, type(np.zeros(1,d).tolist()[0])) for d in (np.float32,np.float64,np.uint32, np.int16)])
Out[51]: 
{<type 'numpy.int16'>: <type 'int'>,
 <type 'numpy.uint32'>: <type 'long'>,
 <type 'numpy.float32'>: <type 'float'>,
 <type 'numpy.float64'>: <type 'float'>}

1
मैं अपने प्रश्न के अंत में एक संभावना के रूप में उस प्रकार के समाधान का उल्लेख करता हूं। लेकिन मैं एक हार्ड-कोडेड के बजाय एक व्यवस्थित समाधान की तलाश कर रहा हूं जो कि कुछ मामलों को कवर करता है। उदाहरण के लिए, यदि सुन्न भविष्य में अधिक dtypes जोड़ता है, तो आपका समाधान टूट जाएगा। इसलिए मैं उस समाधान से खुश नहीं हूं।
13

संभावित dtypes की संख्या अबाधित है। np.dtype('mint8')किसी भी सकारात्मक पूर्णांक के लिए विचार करें m। एग्जॉस्ट मैपिंग नहीं हो सकती। (मुझे यह भी विश्वास नहीं है कि आपके लिए यह रूपांतरण करने के लिए एक अंतर्निहित फ़ंक्शन है। मैं गलत हो सकता हूं, लेकिन मुझे ऐसा नहीं लगता :))
unutbu

2
अजगर प्रकार अजगर dyypes अजगर प्रकार, मुझे यकीन नहीं है कैसे, लेकिन मैं जो भी विधि का उपयोग करना चाहते हैं। मुझे लगता है कि यह अनुमति देने के लिए होना चाहिए, उदाहरण के लिए, गुणक dtypes और अजगर प्रकारों के बीच गुणा (और अन्य संचालन)। मुझे लगता है कि उनकी विधि पूरी तरह से सभी संभव प्रकार के नक्शे को नहीं करती है, लेकिन कम से कम सबसे आम लोगों को जहां यह समझ में आता है।
कोनराडली

यह लगातार काम नहीं करता है: >>> print([numpy.asscalar(x) for x in numpy.linspace(1.0, 0.0, 21)]) [1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.6499999999999999, 0.6, 0.55, 0.5, 0.44999999999999996, 0.3999999999999999, 0.35, 0.29999999999999993, 0.25, 0.19999999999999996, 0.1499999999999999, 0.09999999999999998, 0.04999999999999993, 0.0]जैसा कि आप देखते हैं कि सभी मान सही रूप से परिवर्तित नहीं हुए थे।
एलेक्स एफ

मेरी पिछली टिप्पणी के बाद, यह अजीब तरह से काम करता है, हालांकि मुझे हालांकि आपको नम्पी मूल प्रकार के बजाय पायथन देशी प्रकार पर राउंड लगाने की आवश्यकता होगी:>>> print([numpy.asscalar(round(x,2)) for x in numpy.linspace(1.0, 0.0, 21)]) [1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5, 0.45, 0.4, 0.35, 0.3, 0.25, 0.2, 0.15, 0.1, 0.05, 0.0]
एलेक्स एफ

9

tolist()इसे पूरा करने के लिए एक अधिक सामान्य दृष्टिकोण है। यह किसी भी आदिम dtype में और arrays या matrices में भी काम करता है।

अगर मैं आदिम प्रकार से बुलाया जाता है तो मैं वास्तव में एक सूची नहीं देता

संख्या == 1.15.2

>>> import numpy as np

>>> np_float = np.float64(1.23)
>>> print(type(np_float), np_float)
<class 'numpy.float64'> 1.23

>>> listed_np_float = np_float.tolist()
>>> print(type(listed_np_float), listed_np_float)
<class 'float'> 1.23

>>> np_array = np.array([[1,2,3.], [4,5,6.]])
>>> print(type(np_array), np_array)
<class 'numpy.ndarray'> [[1. 2. 3.]
 [4. 5. 6.]]

>>> listed_np_array = np_array.tolist()
>>> print(type(listed_np_array), listed_np_array)
<class 'list'> [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]


6

मुझे लगता है कि आप केवल सामान्य प्रकार कन्वर्ट फ़ंक्शन लिख सकते हैं जैसे:

import numpy as np

def get_type_convert(np_type):
   convert_type = type(np.zeros(1,np_type).tolist()[0])
   return (np_type, convert_type)

print get_type_convert(np.float32)
>> (<type 'numpy.float32'>, <type 'float'>)

print get_type_convert(np.float64)
>> (<type 'numpy.float64'>, <type 'float'>)

इसका मतलब है कि कोई निश्चित सूची नहीं है और आपका कोड अधिक प्रकारों के साथ स्केल होगा।


क्या आप जानते हैं कि स्रोत कोड सूची के भाग के लिए कहाँ है () विधि जो अजगर प्रकारों के लिए संख्यात्मक प्रकारों को मैप करती है? मैंने त्वरित रूप से देखा, लेकिन वह नहीं मिला।
२६:१२

यह एक हैक है जो मैं कर रहा हूं वह numpy.ndarray1 शून्य का उपयोग करके उत्पन्न कर रहा है zeros()और ndarrays tolist()फ़ंक्शन को मूल प्रकारों में बदलने के लिए कॉल कर रहा है। एक बार देशी प्रकारों में मैं इसे वापसी के प्रकार के लिए कहता हूं। tolist()का एक fucntion हैndarray
मैट ऑकॉक

हाँ, मुझे लगता है कि --- यह जो मैं चाहता हूं उसके लिए काम करता है और इसलिए मैंने आपके समाधान को स्वीकार कर लिया है। लेकिन मुझे आश्चर्य है कि कैसे टोस्ट () यह तय करने का अपना काम करता है कि किस प्रकार का निर्माण किया जाए, और मुझे यकीन नहीं है कि स्रोत कैसे खोजना है।
२६:१२

numpy.sourceforge.net/numdoc/HTML/numdoc.htm#pgfId-36588 वह स्थान है जहाँ फ़ंक्शन को प्रलेखित किया जाता है। मैंने सोचा कि निरीक्षण अधिक जानकारी पाने में मदद करने में सक्षम हो सकता है लेकिन कोई खुशी नहीं। अगले चरण में मैंने github.com/numpy/numpy.git को क्लोन करने और चलाने की कोशिश की grep -r 'tolist' numpy। (अभी भी प्रगति में है, बड़े पैमाने पर भारी है!)
मैट

3

numpy एक मैपिंग में उस जानकारी को उजागर करती है typeDictताकि आप नीचे जैसा कुछ कर सकें ::

>>> import __builtin__
>>> import numpy as np
>>> {v: k for k, v in np.typeDict.items() if k in dir(__builtin__)}
{numpy.object_: 'object',
 numpy.bool_: 'bool',
 numpy.string_: 'str',
 numpy.unicode_: 'unicode',
 numpy.int64: 'int',
 numpy.float64: 'float',
 numpy.complex128: 'complex'}

यदि आप उनके नामों के बजाय वास्तविक अजगर प्रकार चाहते हैं, तो आप कर सकते हैं ::

>>> {v: getattr(__builtin__, k) for k, v in np.typeDict.items() if k in vars(__builtin__)}
{numpy.object_: object,
 numpy.bool_: bool,
 numpy.string_: str,
 numpy.unicode_: unicode,
 numpy.int64: int,
 numpy.float64: float,
 numpy.complex128: complex}

3

आंशिक रूप से देर से आने के लिए क्षमा करें, लेकिन मैं केवल numpy.float64नियमित पायथन में परिवर्तित होने की समस्या को देख रहा था float। मैंने ऐसा करने के 3 तरीके देखे:

  1. npValue.item()
  2. npValue.astype(float)
  3. float(npValue)

यहाँ IPython से प्रासंगिक समय हैं:

In [1]: import numpy as np

In [2]: aa = np.random.uniform(0, 1, 1000000)

In [3]: %timeit map(float, aa)
10 loops, best of 3: 117 ms per loop

In [4]: %timeit map(lambda x: x.astype(float), aa)
1 loop, best of 3: 780 ms per loop

In [5]: %timeit map(lambda x: x.item(), aa)
1 loop, best of 3: 475 ms per loop

ऐसा लगता है कि float(npValue)बहुत तेज लगता है।


1

मेरा दृष्टिकोण थोड़ा ज़बरदस्त है, लेकिन सभी मामलों के लिए अच्छा लगता है:

def type_np2py(dtype=None, arr=None):
    '''Return the closest python type for a given numpy dtype'''

    if ((dtype is None and arr is None) or
        (dtype is not None and arr is not None)):
        raise ValueError(
            "Provide either keyword argument `dtype` or `arr`: a numpy dtype or a numpy array.")

    if dtype is None:
        dtype = arr.dtype

    #1) Make a single-entry numpy array of the same dtype
    #2) force the array into a python 'object' dtype
    #3) the array entry should now be the closest python type
    single_entry = np.empty([1], dtype=dtype).astype(object)

    return type(single_entry[0])

उपयोग:

>>> type_np2py(int)
<class 'int'>

>>> type_np2py(np.int)
<class 'int'>

>>> type_np2py(str)
<class 'str'>

>>> type_np2py(arr=np.array(['hello']))
<class 'str'>

>>> type_np2py(arr=np.array([1,2,3]))
<class 'int'>

>>> type_np2py(arr=np.array([1.,2.,3.]))
<class 'float'>

मैं देखता हूं कि यह मूल रूप से मैट अल्कॉक के उत्तर के समान है।
साइमन स्ट्रेचर

1

उन लोगों के लिए एक स्केल स्केलर के बारे में ध्यान दें, जिन्हें स्वचालित रूपांतरण की आवश्यकता नहीं है और मूल्य के बराबर dtype जानते हैं:

ऐरे स्केलर पाइथन स्कैलर्स से भिन्न होते हैं, लेकिन अधिकांश भाग के लिए उनका उपयोग परस्पर किया जा सकता है (प्राथमिक अपवाद v2.x से अधिक पुराने पाइथन के संस्करणों के लिए है, जहां पूर्णांक सरणी स्केलर सूचियों और टुपल्स के लिए सूचक के रूप में कार्य नहीं कर सकते हैं)। कुछ अपवाद हैं, जैसे कि जब कोड को एक स्केलर के बहुत विशिष्ट गुणों की आवश्यकता होती है या जब यह विशेष रूप से जांचता है कि क्या मूल्य पायथन स्केलर है। आमतौर पर, समस्याओं को आसानी से पाइथन स्केलर्स के लिए स्पष्ट रूप से सरणी स्केलर्स को परिवर्तित करके, इसी पाइथन प्रकार फ़ंक्शन (जैसे, इंट, फ्लोट, कॉम्प्लेक्स, स्ट्र, यूनिकोड) का उपयोग करके तय किया जाता है।

स्रोत

इस प्रकार, अधिकांश मामलों के लिए रूपांतरण की आवश्यकता नहीं हो सकती है, और सरणी स्केलर को सीधे इस्तेमाल किया जा सकता है। प्रभाव पायथन स्केलर के उपयोग के समान होना चाहिए:

>>> np.issubdtype(np.int64, int)
True
>>> np.int64(0) == 0
True
>>> np.issubdtype(np.float64, float)
True
>>> np.float64(1.1) == 1.1
True

लेकिन अगर, किसी कारण से, स्पष्ट रूपांतरण की आवश्यकता होती है, तो इसी अंतर्निहित पायथन का उपयोग करके जाने का तरीका है। जैसा कि अन्य उत्तर में दिखाया गया है कि यह सरणी स्केलर item()विधि से भी तेज है ।


0

एक इकाई डेटा ऑब्जेक्ट के बजाय पूरे ndarray का अनुवाद करें:

def trans(data):
"""
translate numpy.int/float into python native data type
"""
result = []
for i in data.index:
    # i = data.index[0]
    d0 = data.iloc[i].values
    d = []
    for j in d0:
        if 'int' in str(type(j)):
            res = j.item() if 'item' in dir(j) else j
        elif 'float' in str(type(j)):
            res = j.item() if 'item' in dir(j) else j
        else:
            res = j
        d.append(res)
    d = tuple(d)
    result.append(d)
result = tuple(result)
return result

हालाँकि, बड़े डेटाफ़्रेम को संभालने में कुछ मिनट लगते हैं। मैं एक अधिक कुशल समाधान की तलाश में हूं। बेहतर जवाब की उम्मीद है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.