I have a class calling two functions and two instance methods.
class MyClass(object):
def df1(self):
raw_data = {'preTestScore': [4, 24, '', 2, 3],'postTestScore': [25, 94, 57, 62, 70]}
df1 = pd.DataFrame(raw_data, columns = ['preTestScore', 'postTestScore'])
return df1
def df2(self):
raw_data = {'preTestScore': [14, 4, 15, 12, 13],'postTestScore': ['', 4, 7, 2, 7]}
df2 = pd.DataFrame(raw_data, columns = ['preTestScore', 'postTestScore'])
return df2
def df1_and_df2(self):
return (self.df1(), self.df2())
And how to inherit those two dfs from another class
class MySecond():
#call df1 and df2 from MyClass
#work on from those two dfs
Inside the class you could do
obj = MyClass()
obj.dfl()
obj.df2()
You could also have MySecond inherit MyClass by doing
class MySecond(MyClass):
#code
Your MyClass.df1 and MyClass.df2 methods are not depending on a MyClass object, meaning that they could be declared as static methods:
class MyClass(object):
#staticmethod
def df1():
raw_data = {'preTestScore': [4, 24, '', 2, 3],'postTestScore': [25, 94, 57, 62, 70]}
df1 = pd.DataFrame(raw_data, columns = ['preTestScore', 'postTestScore'])
return df1
#staticmethod
def df2():
raw_data = {'preTestScore': [14, 4, 15, 12, 13],'postTestScore': ['', 4, 7, 2, 7]}
df2 = pd.DataFrame(raw_data, columns = ['preTestScore', 'postTestScore'])
return df2
From there they could be called directly from the class anywhere without requiring an instantiated object:
MyClass.df1()
MyClass.df2()
EDIT: To inherit from MyClass, you would do the following:
class MySecond(MyClass):
pass
Now instantiating MySecond would inherits MyClass methods. E.g.
instance = MySecond()
instance.df1_and_df2()
More info about inheritance: https://docs.python.org/3/tutorial/classes.html#inheritance
Related
I have an issue with unit test definition. I am going to test data frames and I do not understand why the following result is returned.
Result:
Ran 0 tests in 0.000s
OK
Script:
import unittest
import pandas as pd
from pandas._testing import assert_frame_equal
def df_minus(df_main:pd.DataFrame, df_subset:pd.DataFrame) -> pd.DataFrame :
return df_main
class TestDataFrameMinus(unittest.TestCase):
def df_minus_equal(self):
df_A = pd.DataFrame(data={
'col1': [1, 2, 3, 4]
}
)
df_B = pd.DataFrame(data={
'col1': [1, 2, 3]
}
)
df_result = pd.DataFrame(data={
'col1': [1, 2, 3]
}
)
assert_frame_equal(df_minus(df_A, df_B), df_result)
if __name__ == '__main__':
unittest.main()
Do you have any idea why the test is not visible?
You should name your methods with test_ prefix
def test_df_minus_equal(self):
pass
I'm trying to use a function to generate a dictionary with some variable fields according to the arguments that I give to the function. The idea is to try multiple configurations and obtain different dictionaries.
I have a function already but it looks non pythonic and it looks very hardcoded.
def build_entry(prefix=None,
field_a=None,
field_b=None,
quantity_a=None,
quantity_b=None,
):
fields = {}
if prefix is not None:
fields['prefix'] = prefix
if field_a is not None:
fields['field_a'] = field_a
if field_b is not None:
fields['field_b'] = field_b
if quantity_a is not None:
fields['quantity_a'] = quantity_a
if quantity_b is not None:
fields['quantity_b'] = quantity_b
return fields
The idea is to call the function like this:
fields = build_entry(*config)
Input: [26, 0, None, None, 20]
Output: {'prefix': 26, 'field_a': 0, 'quantity_b': 5}
Input: [20, 5, None, None, None]
Output: {'prefix': 20, 'field_a':5}
Input: [None, None, 0, 5, None]
Output: {'field_b': 0, 'quantity_a':5}
Any idea how to make this function better or more pythonic? Or there is any function that already does this?
I'm using Python 2.7.
def build_entry(*values):
keys = ['prefix', 'field_a', 'field_b', 'quantity_a', 'quantity_b']
return { k: v for k, v in zip(keys, values) if v is not None}
And then called the same way:
In [1]: build_entry(*[26, 0, None, None, 20])
Out[1]: {'prefix': 26, 'field_a': 0, 'quantity_b': 20}
I think that you want something like this:
def build_entry(**kwargs):
return kwargs
if __name__ == '__main__':
print(build_entry(prefix=1, field_a='a'))
Outputs:
{'prefix': 1, 'field_a': 'a'}
Suppose I have this dictionary:
self.dict = {'A':[[10, 20],[23,76,76],[23,655,54]], 'B':[30, 40, 50], 'C':[60, 100]}
Where the key 'A' is a list of lists. I want to get only the first 2 lists of 'A', i.e. [10, 20],[23,76,76]. I tried the idea of looping but it does not work well. :
class T(object):
def __init__(self):
self.dict = {'A':[[10, 20],[23,76,76],[23,655,54]], 'B':[30, 40, 50], 'C':[60, 100]}
def output(self):
for i in self.dict:
for j in self.dict[i]:
first_two_lists = j
print ("%s" % (first_two_lists))
if __name__ == '__main__':
T().output()
How can I get that ?
>>> d = {'A':[[10, 20],[23,76,76],[23,655,54]], 'B':[30, 40, 50], 'C':[60, 100]}
>>> d['A'][:2]
[[10, 20], [23, 76, 76]]
Using list slicing:
>>> d = {'A':[[10, 20],[23,76,76],[23,655,54]], 'B':[30, 40, 50], 'C':[60, 100]}
>>> d.get('A')[:2]
[[10, 20], [23, 76, 76]]
I currently have a list of lists where every list consists of the same kind of information, say:
[['Planet Name', 16, 19, 27, 11], ['Planet Name 2', 12, 22, 11, 42], ....]
and I would like to use a class to make this into a list of objects with the same information, where index 0 is self.name, index 1 is self.distance and so on for every seperate list.
I know that I need to use some kind of a for loop, but have no idea how to go about and do this.
I would really appreciate some help, trying to learn Python and currently classes!
You can use namedtuple like this, to create an object dynamically, with the list of field names. *item in this code is called, unpacking of arguments list
from collections import namedtuple
Planet = namedtuple("Planet", ["name", "distance", "a", "b", "c"])
data = [['Planet Name', 16, 19, 27, 11],['Planet Name 2', 12, 22, 11, 42]]
for item in data:
planet = Planet(*item)
print planet.name, planet.distance, planet
Output
Planet Name 16 Planet(name='Planet Name', distance=16, a=19, b=27, c=11)
Planet Name 2 12 Planet(name='Planet Name 2', distance=12, a=22, b=11, c=42)
Note: namedtuple is a subclass of tuple. So, all the objects created with namedtuple are immutable. It means that, once the object is created, data in the member variables cannot be changed.
Well... To make a class like you want you can do something like this:
class Planet(object):
def __init__(self, *args, **kwargs):
self.name = args[0]
self.distance = args[1]
# ... etc ...
Or something like this:
class Planet(object):
def __init__(self, name, distance, ...):
self.name = name
self.distance = distance
# ... etc ...
And then you call it like this:
p = Planet(*['Planet Name', 16, 19, 27, 11])
In a loop that would be:
l = [['Planet Name', 16, 19, 27, 11], ['Planet Name 2', 12, 22, 11, 42], ....]
planets = [Planet(*data) for data in l]
I'm confused. Have you created the Planet constructor yet?
The code would be something like:
class Planet(object):
def __init__(self, ....):
....
planets = [['Planet Name', 16, 19, 27, 11]['Planet Name 2', 12, 22, 11, 42]....]
planet_list = [Planet(*p) for p in planets]
If you don't want to have a constructor (__init__) which knows about the specifics of your lists, you could do it like this
lists = [['Planet Name', 16, 19, 27, 11], ['Planet Name 2', 12, 22, 11, 42]]
class Planet(object):
pass
for l in lists:
planet = Planet()
setattr(planet, 'name', l[0])
setattr(planet, 'distance', l[1])
setattr(planet, 'size', l[2])
print planet.name, planet.distance, planet.size
I'm working on my first python script, which creates and updates and object with different datetime entries.
I'm setting up the object like this:
# Date conversion
import datetime
import time
# 0:01:00 and 0:00:00 threshold and totalseconds
threshold = time.strptime('00:01:00,000'.split(',')[0],'%H:%M:%S')
tick = datetime.timedelta(hours=threshold.tm_hour,minutes=threshold.tm_min,seconds=threshold.tm_sec).total_seconds()
zero_time = datetime.timedelta(hours=0,minutes=0,seconds=0)
zero_tick = zero_time.total_seconds()
format_date = '%d/%b/%Y:%H:%M:%S'
from datetime import datetime
# Response object
class ResponseObject(object):
def __init__(self, dict):
self.__dict__ = dict
# JSON encoding
from json import JSONEncoder
class MyEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
# > check for JSON response object
try:
obj
except NameError:
obj = ResponseObject({})
...
entry = "14/Nov/2012:09:32:31 +0100"
entry_tz = str.join(' ', entry.split(None)[1:6])
entry_notz = entry.replace(' '+entry_tz,'')
this_time = datetime.strptime(entry_notz, format_date)
# > add machine to object if not there, add init time
if not hasattr(obj, "SOFTINST"):
#line-breaks for readability
setattr(obj, "SOFTINST", {
"init":this_time,
"last":this_time,
"downtime":zero_time,
"totaltime":"",
"percentile":100
})
...
print this_time
print MyEncoder().encode({"hello":"bar"})
print getattr(obj, "SOFTINST")
My last 'print' returns this:
{
'totaltime': datetime.timedelta(0),
'uptime': '',
'last': datetime.datetime(2012, 11, 14, 9, 32, 31),
'init': datetime.datetime(2012, 11, 14, 9, 32, 31),
'percentile': 100,
'downtime': 0
}
Which I cannot convert into JSON...
I don't understand why this:
print this_time #2012-11-14 09:32:31
but inside the object, it's stored as
datetime.datetime(2012, 11, 14, 9, 32, 31)
Question:
How do I store datetime objects in "string format" and still have them easily accessible (and modifyable) in Python?
Thanks!
Use the isoformat method on the datetime object. (see reference: http://docs.python.org/release/2.5.2/lib/datetime-datetime.html)