पंक्तियों को अनुक्रमित और सम्मिलित करते समय पंडों के डेटा फ्रेम के जोर से रोकें


16

मैं पंडों के डेटा फ्रेम की अलग-अलग पंक्तियों के साथ काम कर रहा हूं, लेकिन पंक्तियों को अनुक्रमित और सम्मिलित करते समय मैं ज़बरदस्ती के मुद्दों पर ठोकर खा रहा हूं। लगता है कि पंडों को हमेशा एक मिश्रित इंट / फ्लोट से सभी-फ्लोट प्रकारों के लिए मजबूर करना पड़ता है, और मैं इस व्यवहार पर कोई स्पष्ट नियंत्रण नहीं देख सकता हूं।

उदाहरण के लिए, यहाँ के साथ एक सरल डेटा फ्रेम है aके रूप में intऔर bके रूप में float:

import pandas as pd
pd.__version__  # '0.25.2'

df = pd.DataFrame({'a': [1], 'b': [2.2]})
print(df)
#    a    b
# 0  1  2.2
print(df.dtypes)
# a      int64
# b    float64
# dtype: object

यहाँ एक पंक्ति को अनुक्रमित करते समय एक ज़बरदस्त मुद्दा है:

print(df.loc[0])
# a    1.0
# b    2.2
# Name: 0, dtype: float64
print(dict(df.loc[0]))
# {'a': 1.0, 'b': 2.2}

और यहाँ एक पंक्ति सम्मिलित करते समय एक ज़बरदस्त मुद्दा है:

df.loc[1] = {'a': 5, 'b': 4.4}
print(df)
#      a    b
# 0  1.0  2.2
# 1  5.0  4.4
print(df.dtypes)
# a    float64
# b    float64
# dtype: object

दोनों उदाहरणों में, मैं चाहता हूं कि aस्तंभ एक पूर्णांक प्रकार के रूप में बना रहे, न कि एक फ्लोट प्रकार के लिए मजबूर होने के बजाय।


मुझे यह मिल गया , लेकिन प्रभावी ढंग से समस्या हल होने पर मैं नहीं मिला। इस बीच के समय में मुझे लगता है कि आप कर सकते हैं:df.loc[[0], df.columns]
दानी मेज़ो


Pd.DataFrame जैसी ध्वनियाँ तात्कालिकता पर मिश्रण प्रकार का समर्थन नहीं करती हैं? pandas.pydata.org/pandas-docs/stable/reference/api/… dtype param केवल एक प्रकार का समर्थन करता है। .read_[type]हालांकि कई dtypes का समर्थन करता है ...
क्वेंटिन

जवाबों:


4

कुछ खुदाई के बाद, यहाँ कुछ भयानक बदसूरत वर्कअराउंड हैं। (बेहतर उत्तर स्वीकार किया जाएगा।)

यहां पाया जाने वाला एक विचित्र यह है कि गैर-संख्यात्मक कॉलम जबरदस्ती बंद कर देता है, इसलिए यहां बताया गया है कि एक पंक्ति को किस प्रकार अनुक्रमणित किया जाए dict:

dict(df.assign(_='').loc[0].drop('_', axis=0))
# {'a': 1, 'b': 2.2}

और एक पंक्ति सम्मिलित करके एक नया डेटा फ्रेम एक पंक्ति के साथ बनाया जा सकता है:

df = df.append(pd.DataFrame({'a': 5, 'b': 4.4}, index=[1]))
print(df)
#    a    b
# 0  1  2.2
# 1  5  4.4

इन दोनों तरकीबों को बड़े डेटा फ्रेम के लिए अनुकूलित नहीं किया गया है, इसलिए मैं बेहतर उत्तर की सराहना करूंगा!


आप हमेशा सिर्फ मोटे तौर पर पोस्ट कर सकते हैं df['a'] = df.a.astype(mytype)... यह अभी भी गंदा है और शायद कुशल नहीं है।
क्वेंटिन

.astype()फ्लोट के लिए खतरनाक है -> पूर्णांक; इसे बदलने कोई समस्या नहीं है 1.1करने के लिए 1, ताकि आप वास्तव में सुनिश्चित करें कि सभी के अपने मूल्यों यह करने से पहले 'पूर्णांक की तरह' कर रहे हैं करने की आवश्यकता है,। शायद सबसे अच्छा उपयोग करने के लिए pd.to_numericसाथdowncast='integer'
ALollz

2

समस्या की जड़ वह है

  1. पांडा डेटाफ्रेम का अनुक्रमण एक पांडा श्रृंखला देता है

हम देख सकते हैं कि:

type(df.loc[0])
# pandas.core.series.Series

और एक श्रृंखला में केवल एक dtype हो सकता है, आपके मामले में या तो int64 या float64।

मेरे सिर पर दो वर्कअराउंड आते हैं:

print(df.loc[[0]])
# this will return a dataframe instead of series
# so the result will be
#    a    b
# 0  1  2.2

# but the dictionary is hard to read
print(dict(df.loc[[0]]))
# {'a': 0    1
# Name: a, dtype: int64, 'b': 0    2.2
# Name: b, dtype: float64}

या

print(df.astype(object).loc[0])
# this will change the type of value to object first and then print
# so the result will be
# a      1
# b    2.2
# Name: 0, dtype: object

print(dict(df.astype(object).loc[0]))
# in this way the dictionary is as expected
# {'a': 1, 'b': 2.2}
  1. जब आप किसी शब्दकोश को किसी डेटाफ़्रेम में जोड़ते हैं, तो वह शब्दकोश को पहले एक श्रृंखला में बदल देगा और फिर जोड़ देगा। (तो वही समस्या फिर से होती है)

https://github.com/pandas-dev/pandas/blob/master/pandas/core/frame.py#L6973

if isinstance(other, dict):
    other = Series(other)

तो आपका चलना वास्तव में एक ठोस है, या फिर हम कर सकते हैं:

df.append(pd.Series({'a': 5, 'b': 4.4}, dtype=object, name=1))
#    a    b
# 0  1  2.2
# 1  5  4.4

objectडेटा प्रकारों का उपयोग करने के लिए अच्छा विचार है ! एक और एक शुरुआत से एक ऑब्जेक्ट डेटाफ़्रेम बनाने के लिए है:df = pd.DataFrame({'a': [1], 'b': [2.2]}, dtype=object)
माइक टी

2

जब भी आप डेटाफ़्रेम या अपडाउन डेटा से डेटाफ़्रेम में डेटा प्राप्त कर रहे हों और डेटा को समान रखने की आवश्यकता हो, तो अन्य आंतरिक संरचनाओं में रूपांतरण से बचें जो आवश्यक डेटा प्रकारों से अवगत नहीं हैं।

जब आप df.loc[0]इसे करने के लिए धर्मान्तरित pd.Series,

>>> type(df.loc[0])
<class 'pandas.core.series.Series'>

और अब, Seriesकेवल एक ही होगा dtype। इस प्रकार मजबूर intकरने के लिए float

इसके बजाय संरचना रखें pd.DataFrame,

>>> type(df.loc[[0]])
<class 'pandas.core.frame.DataFrame'>

फ़्रेम के रूप में आवश्यक पंक्ति का चयन करें और फिर में कनवर्ट करें dict

>>> df.loc[[0]].to_dict(orient='records')
[{'a': 1, 'b': 2.2}]

इसी तरह, एक नई पंक्ति जोड़ने के लिए, पांडा pd.DataFrame.appendफ़ंक्शन का उपयोग करें ,

>>> df = df.append([{'a': 5, 'b': 4.4}]) # NOTE: To append as a row, use []
   a    b
0  1  2.2
0  5  4.4

उपरोक्त प्रकार से रूपांतरण नहीं होगा,

>>> df.dtypes
a      int64
b    float64
dtype: object

वाह उस कोड कोड को तीन बार पढ़ना था। वह बहुत सूक्ष्म है। यह अतीत में मैंने जो कुछ किया है, उससे बेहतर है ... अंतिम डेटाफ्रेम के माध्यम से लूप और सही डेटा प्रकार के साथ मानों को पुन: असाइन करें (हाँ मैंने जो किया वह एक भयानक समाधान है जो वास्तव में पैमाने पर नहीं होगा।)।
वनबंतम

1
ओह। खुशी है कि इसने @VanBantam
विष्णुदेव

1

मामूली डेटा जोड़तोड़ के साथ एक अलग दृष्टिकोण:

मान लें कि आपके पास शब्दकोशों (या डेटाफ़्रेम) की एक सूची है

lod=[{'a': [1], 'b': [2.2]}, {'a': [5], 'b': [4.4]}]

जहां प्रत्येक शब्दकोश एक पंक्ति का प्रतिनिधित्व करता है (दूसरे शब्दकोश में सूचियों पर ध्यान दें)। फिर आप आसानी से एक डेटाफ्रेम बना सकते हैं:

pd.concat([pd.DataFrame(dct) for dct in lod])
   a    b
0  1  2.2
0  5  4.4

और आप स्तंभों के प्रकारों को बनाए रखते हैं। कॉनसैट देखें

इसलिए यदि आपके पास डेटाफ़्रेम और डिसकस की सूची है, तो आप इसका उपयोग कर सकते हैं

pd.concat([df] + [pd.DataFrame(dct) for dct in lod])

0

पहले मामले में, आप अशक्त पूर्णांक डेटा प्रकार के साथ काम कर सकते हैं । श्रृंखला चयन में कोई अंतर नहीं है floatऔर मान एक objectकंटेनर में रखे गए हैं । शब्दकोश तब ठीक से बनाया गया है, अंतर्निहित मूल्य के रूप में संग्रहीत np.int64

df = pd.DataFrame({'a': [1], 'b': [2.2]})
df['a'] = df['a'].astype('Int64')

d = dict(df.loc[0])
#{'a': 1, 'b': 2.2}

type(d['a'])
#numpy.int64

आपके सिंटैक्स के साथ, यह लगभग दूसरे मामले के लिए भी काम करता है, लेकिन यह objectबहुत अच्छा नहीं है:

df.loc[1] = {'a': 5, 'b': 4.4}
#   a    b
#0  1  2.2
#1  5  4.4

df.dtypes
#a     object
#b    float64
#dtype: object

हालाँकि, हम अंत में एक पंक्ति (एक रेंजइंडेक्स के साथ) जोड़ने के लिए सिंटैक्स में एक छोटा सा बदलाव कर सकते हैं और अब प्रकारों को ठीक से निपटाया जाता है।

df = pd.DataFrame({'a': [1], 'b': [2.2]})
df['a'] = df['a'].astype('Int64')

df.loc[df.shape[0], :] = [5, 4.4]
#   a    b
#0  1  2.2
#1  5  4.4

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