python - منع إكراه إطارات بيانات الباندا أثناء فهرسة وإدراج صفوف




pandas coercion (4)

أنا أعمل مع صفوف فردية من إطارات بيانات الباندا ، لكنني أعثر على مشاكل الإكراه أثناء فهرسة وإدراج صفوف. يبدو أن Pandas ترغب دائمًا في الإكراه من أنواع int / float مختلطة إلى جميع أنواع float ، ولا يمكنني رؤية أي ضوابط واضحة على هذا السلوك.

على سبيل المثال ، في ما يلي إطار بيانات بسيط به a int و b :

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

في كلتا الحالتين ، أريد أن يظل العمود كنوع صحيح ، بدلاً من الإكراه على نوع عائم.


بعد بعض الحفر ، إليك بعض الحلول القبيحة بشكل رهيب. (سيتم قبول إجابة أفضل.)

الغريب هنا هو أن الأعمدة غير الرقمية تتوقف عن الإكراه ، لذلك هنا هي كيفية فهرسة صف واحد إلى 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

لم يتم تحسين كلتا الحيلتين لإطارات البيانات الكبيرة ، لذلك سأكون ممتنًا للحصول على إجابة أفضل!


جذر المشكلة هو ذلك

  1. إرجاع فهرسة dataframe الباندا سلسلة الباندا

يمكننا أن نرى أن:

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

كلما كنت تحصل على بيانات من إطار البيانات أو إلحاق البيانات في إطار بيانات وتحتاج إلى الحفاظ على نوع البيانات كما هو ، تجنب التحويل إلى هياكل داخلية أخرى ليست على دراية بأنواع البيانات المطلوبة.

عندما تفعل df.loc[0] فإنه يتحول إلى pd.Series ،

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

والآن ، سوف Series لديها فقط نوع dtype . وبالتالي الإكراه int float .

بدلا من الحفاظ على هيكل pandas.pydata.org/pandas-docs/stable/reference/api/… ،

>>> 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

نهج مختلف مع التلاعب في البيانات طفيفة:

افترض أن لديك قائمة من القواميس (أو قواعد البيانات)

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

وأنت تحافظ على أنواع الأعمدة. انظر concat

لذلك إذا كان لديك قاعدة بيانات وقائمة من الرسوم ، يمكنك استخدامها فقط

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




coercion