পান্ডাস ডেটা ফ্রেমের সাবক্লাসের জন্য সম্পত্তি সেটেটর


9

আমি pd.DataFrame( groupএবং timestamp_col) আরম্ভ করার সময় এর দুটি প্রয়োজনীয় আর্গুমেন্ট রয়েছে তার একটি উপশ্রেণী সেট আপ করার চেষ্টা করছি । আমি argu যুক্তিগুলিতে বৈধতা চালাতে চাই groupএবং timestamp_colতাই প্রতিটি বৈশিষ্ট্যের জন্য আমার কাছে সেটার পদ্ধতি রয়েছে। যতক্ষণ না চেষ্টা করব set_index()এবং না পাচ্ছি ততক্ষণ এই সমস্ত কাজ করে TypeError: 'NoneType' object is not iterable। এটি প্রদর্শিত হয় যে আমার সেটার ফাংশনে test_set_indexএবং এর মধ্যে কোনও যুক্তি পাস করা হচ্ছে না test_assignment_with_indexed_obj। আমি যদি if g == None: returnআমার সেটার ফাংশনে যুক্ত করি তবে আমি পরীক্ষার কেসগুলি পাস করতে পারি তবে এটি সঠিক সমাধান বলে মনে করবেন না।

এই প্রয়োজনীয় যুক্তিগুলির জন্য আমি কীভাবে সম্পত্তি বৈধতা প্রয়োগ করব?

নীচে আমার ক্লাস:

import pandas as pd
import numpy as np


class HistDollarGains(pd.DataFrame):
    @property
    def _constructor(self):
        return HistDollarGains._internal_ctor

    _metadata = ["group", "timestamp_col", "_group", "_timestamp_col"]

    @classmethod
    def _internal_ctor(cls, *args, **kwargs):
        kwargs["group"] = None
        kwargs["timestamp_col"] = None
        return cls(*args, **kwargs)

    def __init__(
        self,
        data,
        group,
        timestamp_col,
        index=None,
        columns=None,
        dtype=None,
        copy=True,
    ):
        super(HistDollarGains, self).__init__(
            data=data, index=index, columns=columns, dtype=dtype, copy=copy
        )

        self.group = group
        self.timestamp_col = timestamp_col

    @property
    def group(self):
        return self._group

    @group.setter
    def group(self, g):
        if g == None:
            return

        if isinstance(g, str):
            group_list = [g]
        else:
            group_list = g

        if not set(group_list).issubset(self.columns):
            raise ValueError("Data does not contain " + '[' + ', '.join(group_list) + ']')
        self._group = group_list

    @property
    def timestamp_col(self):
        return self._timestamp_col

    @timestamp_col.setter
    def timestamp_col(self, t):
        if t == None:
            return
        if not t in self.columns:
            raise ValueError("Data does not contain " + '[' + t + ']')
        self._timestamp_col = t

এখানে আমার পরীক্ষার মামলাগুলি রয়েছে:

import pytest

import pandas as pd
import numpy as np

from myclass import *


@pytest.fixture(scope="module")
def sample():
    samp = pd.DataFrame(
        [
            {"timestamp": "2020-01-01", "group": "a", "dollar_gains": 100},
            {"timestamp": "2020-01-01", "group": "b", "dollar_gains": 100},
            {"timestamp": "2020-01-01", "group": "c", "dollar_gains": 110},
            {"timestamp": "2020-01-01", "group": "a", "dollar_gains": 110},
            {"timestamp": "2020-01-01", "group": "b", "dollar_gains": 90},
            {"timestamp": "2020-01-01", "group": "d", "dollar_gains": 100},
        ]
    )

    return samp

@pytest.fixture(scope="module")
def sample_obj(sample):
    return HistDollarGains(sample, "group", "timestamp")

def test_constructor_without_args(sample):
    with pytest.raises(TypeError):
        HistDollarGains(sample)


def test_constructor_with_string_group(sample):
    hist_dg = HistDollarGains(sample, "group", "timestamp")
    assert hist_dg.group == ["group"]
    assert hist_dg.timestamp_col == "timestamp"


def test_constructor_with_list_group(sample):
    hist_dg = HistDollarGains(sample, ["group", "timestamp"], "timestamp")

def test_constructor_with_invalid_group(sample):
    with pytest.raises(ValueError):
        HistDollarGains(sample, "invalid_group", np.random.choice(sample.columns))

def test_constructor_with_invalid_timestamp(sample):
    with pytest.raises(ValueError):
        HistDollarGains(sample, np.random.choice(sample.columns), "invalid_timestamp")

def test_assignment_with_indexed_obj(sample_obj):
    b = sample_obj.set_index(sample_obj.group + [sample_obj.timestamp_col])

def test_set_index(sample_obj):
    # print(isinstance(a, pd.DataFrame))
    assert sample_obj.set_index(sample_obj.group + [sample_obj.timestamp_col]).index.names == ['group', 'timestamp']

1
যদি সম্পত্তিটির Noneজন্য একটি অবৈধ মান হয় group, আপনি কি উত্থাপন করবেন না ValueError?
চিপনার

1
আপনি ঠিক বলেছেন যে Noneএটি একটি অবৈধ মান, যে কারণে আমি যদি বিবৃতি পছন্দ করি না। তবে যোগ করে যে কেউই এটি পরীক্ষায় উত্তীর্ণ হয় না। আমি যদি বিবৃতি না হয় তবে কীভাবে এটি সঠিকভাবে ঠিক করতে হবে তা আমি সন্ধান করছি।
সিপেজ

2
সেটারটি একটি উত্থাপন করা উচিত ValueError। সমস্যাটি প্রথমে groupবিশিষ্টটি কী সেট করতে চেষ্টা করছে তা নির্ধারণ করা None
চিপনার

@ চেপার হ্যাঁ, ঠিক আছে।
সিপেজ

হতে পারে পান্ডাস ফ্লেভার প্যাকেজ সাহায্য করতে পারে।
মাইকোলা জোটকো

উত্তর:


3

set_index()পদ্ধতি ডাকব self.copy()আপনার DataFrame বস্তুর একটি অনুলিপি তৈরি (উৎস কোড দেখতে অভ্যন্তরীণভাবে এখানে ), যা ভিতরে এটি আপনার কাস্টমাইজড কন্সট্রাকটর পন্থাটি ব্যবহার করে, _internal_ctor()নতুন বস্তু (তৈরি করতে উৎস )। দ্রষ্টব্য যা self._constructor()অনুরূপ self._internal_ctor(), যা ডিপ-অনুলিপি বা কাটা কাটার মতো ক্রিয়াকলাপ চলাকালীন নতুন ইনস্ট্যান্স তৈরির জন্য প্রায় সকল পান্ডার ক্লাসের জন্য একটি সাধারণ অভ্যন্তরীণ পদ্ধতি। আপনার সমস্যাটি আসলে এই ফাংশন থেকে উদ্ভূত:

class HistDollarGains(pd.DataFrame):
    ...
    @classmethod
    def _internal_ctor(cls, *args, **kwargs):
        kwargs["group"]         = None
        kwargs["timestamp_col"] = None
        return cls(*args, **kwargs) # this is equivalent to calling
                                    # HistDollarGains(data, group=None, timestamp_col=None)

আমার ধারণা আপনি গিথুব ইস্যু থেকে এই কোডটি অনুলিপি করেছেন । লাইনগুলি kwargs["**"] = Noneস্পষ্টতই কনস্ট্রাক্টরকে Noneউভয়কে সেট করতে বলে groupএবং timestamp_col। অবশেষে সেটার / বৈধকারী Noneনতুন মান হিসাবে পায় এবং একটি ত্রুটি বাড়ায়।

অতএব, আপনার groupএবং এর কাছে একটি গ্রহণযোগ্য মান সেট করা উচিত timestamp_col

    @classmethod
    def _internal_ctor(cls, *args, **kwargs):
        kwargs["group"]         = []
        kwargs["timestamp_col"] = 'timestamp' # or whatever name that makes your validator happy
        return cls(*args, **kwargs)

তারপরে আপনি if g == None: returnবৈধকরণকারীটিতে থাকা লাইনগুলি মুছতে পারেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.