Home > OS >  Can't get past this TypeError in python when dealing with imported XML file
Can't get past this TypeError in python when dealing with imported XML file

Time:02-18

I'm trying to sort the imported data from an XML, then slicing it to take the first 10 and returning it to the my_func dictionary to then print out the rows of data from the key being called by the for loop

from helper import fixNumber
import xml.etree.cElementTree as ET

tree = ET.parse("properties.xml")
root = tree.getroot()

list = []

for child in root:
    data = child.attrib.copy()
    data['netIncome'] = fixNumber(child.text)
    data["id"] = (data["id"])
    data['cost'] = fixNumber(data['cost'])
    data['downPayment'] = fixNumber(data['downPayment'])
    data['state'] = (data['state'])
    data['percentage'] = fixNumber(data['percentage'])
    list.append(data)


def top_ten(data):  # sort top ten by cost in descending order
    return data['cost']


list.sort(key=top_ten, reverse=True)

for x in list[:10]:
    print(x)


if __name__ == '__main__':
    my_func = {
        1: top_ten

    }

    for key in my_func:
        funct = my_func[key]
        print(f"{key}", funct())



This is the TypeError I keep getting

Traceback (most recent call last):
  File "/Users/school/VisualStudio/01.LESSON/properties.py", line 40, in <module>
    print(f"{key}", funct())
TypeError: top_ten() missing 1 required positional argument: 'data'

when I type data inside the parathesis of funct, it only prints one data point of an attribute ie. 1 144000.0 which is just one net income from the data

I need to print out the first 10 rows of all the attributes with all the data, sorted. hope this makes sense.

This is a sample of the properties.xml file

<properties>
    <property id="H00001" cost="106000"  downPayment="24380" state="NM" percentage="0.12">2925.6</property>
    <property id="H00002" cost="125000"  downPayment="30000" state="AZ" percentage="0.15">4500</property>
    <property id="H00003" cost="119000"  downPayment="24990" state="NH" percentage="0.13">3248.7</property>
    <property id="H00004" cost="124000"  downPayment="31000" state="MI" percentage="0.19">5890</property>
    <property id="H00005" cost="143000"  downPayment="34320" state="CZ" percentage="0.11">3775.2</property>
    <property id="H00006" cost="139000"  downPayment="30580" state="VI" percentage="0.12">3669.6</property>
    <property id="H00007" cost="132000"  downPayment="26400" state="ND" percentage="0.19">5016</property>
    <property id="H00008" cost="134000"  downPayment="26800" state="CZ" percentage="0.17">4556</property>
    <property id="H00009" cost="143000"  downPayment="34320" state="PA" percentage="0.14">4804.8</property>
    <property id="H00010" cost="123000"  downPayment="25830" state="IN" percentage="0.2">5166</property>
</properties>

the output should look like this but sorted by cost

1 {'id': 'H00012', 'cost': 150000.0, 'downPayment': 36000.0, 'state': 'OR', 'percentage': 0.11, 'netIncome': 3960.0}
{'id': 'H00061', 'cost': 150000.0, 'downPayment': 34500.0, 'state': 'MD', 'percentage': 0.1, 'netIncome': 3450.0}
{'id': 'H00072', 'cost': 150000.0, 'downPayment': 31500.0, 'state': 'MI', 'percentage': 0.15, 'netIncome': 4725.0}
2 {'id': 'H00012', 'cost': 150000.0, 'downPayment': 36000.0, 'state': 'OR', 'percentage': 0.11, 'netIncome': 3960.0}
{'id': 'H00061', 'cost': 150000.0, 'downPayment': 34500.0, 'state': 'MD', 'percentage': 0.1, 'netIncome': 3450.0}
{'id': 'H00072', 'cost': 150000.0, 'downPayment': 31500.0, 'state': 'MI', 'percentage': 0.15, 'netIncome': 4725.0}

CodePudding user response:

There are a few things to improve in your code, but jumping straight to the solution, you need to adjust these things:

  • Your sorting function
def top_ten(ys):  # sort top ten by cost in descending order
    # sort the list of dicts by desc order
    sorted_list = sorted(ys, key=lambda d: -d['cost'])
    # print first 10 elements
    for elem in sorted_list[:10]:
        print(elem)
  • Your main call should be like
if __name__ == '__main__':
    my_func = {
        1: top_ten

    }

    for key in my_func:
        funct = my_func[key]
        print(f"{key}", funct(list))

With these changes you should get this output

1:
{'id': 'H00005', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'CZ', 'percentage': 0.11, 'netIncome': 3775.2}
{'id': 'H00009', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'PA', 'percentage': 0.14, 'netIncome': 4804.8}
{'id': 'H00006', 'cost': 139000.0, 'downPayment': 30580.0, 'state': 'VI', 'percentage': 0.12, 'netIncome': 3669.6}
{'id': 'H00008', 'cost': 134000.0, 'downPayment': 26800.0, 'state': 'CZ', 'percentage': 0.17, 'netIncome': 4556.0}
{'id': 'H00007', 'cost': 132000.0, 'downPayment': 26400.0, 'state': 'ND', 'percentage': 0.19, 'netIncome': 5016.0}
{'id': 'H00002', 'cost': 125000.0, 'downPayment': 30000.0, 'state': 'AZ', 'percentage': 0.15, 'netIncome': 4500.0}
{'id': 'H00004', 'cost': 124000.0, 'downPayment': 31000.0, 'state': 'MI', 'percentage': 0.19, 'netIncome': 5890.0}
{'id': 'H00010', 'cost': 123000.0, 'downPayment': 25830.0, 'state': 'IN', 'percentage': 0.2, 'netIncome': 5166.0}
{'id': 'H00003', 'cost': 119000.0, 'downPayment': 24990.0, 'state': 'NH', 'percentage': 0.13, 'netIncome': 3248.7}
{'id': 'H00001', 'cost': 106000.0, 'downPayment': 24380.0, 'state': 'NM', 'percentage': 0.12, 'netIncome': 2925.6}

An even cleaner version of your code:

import xml.etree.cElementTree as ET

def load_data(fpath="properties.xml"):
    tree = ET.parse(fpath)
    root = tree.getroot()

    xs = []

    for child in root:
        data = child.attrib.copy()
        data['netIncome'] = float(child.text)
        data["id"] = data["id"]
        data['cost'] = float(data['cost'])
        data['downPayment'] = float(data['downPayment'])
        data['state'] = data['state']
        data['percentage'] = float(data['percentage'])
        xs.append(data)

    return xs


def top_ten(ys):  # sort top ten by cost in descending order
    sorted_list = sorted(ys, key=lambda d: -d['cost'])
    for elem in sorted_list[:10]:
        print(elem)


def get_avg_netincome(xs):
    c = 0
    for x in xs:
        c  = x['netIncome']
    print(f'Average net income: {round(c / len(xs), 2)}')


if __name__ == '__main__':
    my_func = {
        1: top_ten,
        2: get_avg_netincome,

    }

    for funct_id, funct in my_func.items():
        print(f'Function id: {funct_id}')
        data = load_data()
        funct(data)
        print()

Which produces the same output:

Function id: 1
{'id': 'H00005', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'CZ', 'percentage': 0.11, 'netIncome': 3775.2}
{'id': 'H00009', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'PA', 'percentage': 0.14, 'netIncome': 4804.8}
{'id': 'H00006', 'cost': 139000.0, 'downPayment': 30580.0, 'state': 'VI', 'percentage': 0.12, 'netIncome': 3669.6}
{'id': 'H00008', 'cost': 134000.0, 'downPayment': 26800.0, 'state': 'CZ', 'percentage': 0.17, 'netIncome': 4556.0}
{'id': 'H00007', 'cost': 132000.0, 'downPayment': 26400.0, 'state': 'ND', 'percentage': 0.19, 'netIncome': 5016.0}
{'id': 'H00002', 'cost': 125000.0, 'downPayment': 30000.0, 'state': 'AZ', 'percentage': 0.15, 'netIncome': 4500.0}
{'id': 'H00004', 'cost': 124000.0, 'downPayment': 31000.0, 'state': 'MI', 'percentage': 0.19, 'netIncome': 5890.0}
{'id': 'H00010', 'cost': 123000.0, 'downPayment': 25830.0, 'state': 'IN', 'percentage': 0.2, 'netIncome': 5166.0}
{'id': 'H00003', 'cost': 119000.0, 'downPayment': 24990.0, 'state': 'NH', 'percentage': 0.13, 'netIncome': 3248.7}
{'id': 'H00001', 'cost': 106000.0, 'downPayment': 24380.0, 'state': 'NM', 'percentage': 0.12, 'netIncome': 2925.6}

Function id: 2
Average net income: 4355.19
  • Related