Mir fehlt gerade total ein passender Ansatz
Ich habe eine Tabelle, darin stehen u.a. drin Flächen und ein jewiliges Datum, wann die Fläche aufgenommen wurde: (so ungefähr)
Name Fläche Datum
x 23 1996
x 4 2000
x 56 2000
y 7 1998
y 12 1998
Ich brauche am Ende das Datum, was den größte Flächenanteil einnimmt für den jeweiligen Namen.
Hatte überlegt, einfach die Flächen aufzusummieren, wenn das Datum gleich ist, aber ich weiß vorher nicht, wieviele Einträge ich überhaupt vergleichen muss, das ist unterschiedlich. Ich kann auch nicht so ganz beliebig durch die Tabelle hin und herspringen.
Hatte überlegt, dass so lange Name x ich Fläche und Datum in eine List, bzw dict scheibe und dann gucke, aber ich weiß da gerade nicht so recht weiter.
Hat wer eine Idee, wie ich das am besten machen könnte?
Suche Ansatz: Flächen abhängig von anderen Attribut summiere
Mal sehen ob ich's richtig verstanden habe: Aus den Daten willst alle Flächenwerte mit gleichem Namen und gleicher Jahreszahl aufaddieren und dann pro Namen jeweils das Jahr mit der grössten Fläche wissen!?
Also aufaddieren im Beispiel:
Name Fläche Datum
x 23 1996
x 60 2000
y 19 1998
Und Endergebnis dann:
x 2000
y 1998
Wenn die erste Zeile der Ausgangsdaten 'x 58 1996' lauten würde, wäre trotzdem 'x 2000' die richtige Antwort?
Kann man irgendwelche Annahmen über die Reihenfolge der Ausgangsdaten machen? In Deinem Beispiel sind die ja nach Namen und dann nach Jahr sortiert. Zufall?
Für den unsortierten Fall ist das hier ein Lösungsansatz:
Wenn die Daten aus der Tabelle nach Namen oder nach Namen und Jahr sortiert sind, geht's ein wenig effizienter.
Also aufaddieren im Beispiel:
Name Fläche Datum
x 23 1996
x 60 2000
y 19 1998
Und Endergebnis dann:
x 2000
y 1998
Wenn die erste Zeile der Ausgangsdaten 'x 58 1996' lauten würde, wäre trotzdem 'x 2000' die richtige Antwort?
Kann man irgendwelche Annahmen über die Reihenfolge der Ausgangsdaten machen? In Deinem Beispiel sind die ja nach Namen und dann nach Jahr sortiert. Zufall?
Für den unsortierten Fall ist das hier ein Lösungsansatz:
Code: Alles auswählen
from collections import defaultdict
def aggregate_years(table):
result = defaultdict(int)
for name, area, year in table:
result[name, year] += area
return ((name, area, year) for (name, year), area in result.iteritems())
def largest_areas(table):
result = defaultdict(lambda: (0, 0))
for name, area, year in aggregate_years(table):
result[name] = max(result[name], (area, year))
return dict((name, year) for (name, (area, year)) in result.iteritems())
def main():
table = (('x', 23, 1996),
('x', 4, 2000),
('x', 56, 2000),
('y', 7, 1998),
('y', 12, 1998))
print largest_areas(table) # => {'y': 1998, 'x': 2000}
Also die Daten sind nach Namen sortiert. Und der ist für mich nicht relevant, weil sobald sich der Name ändert, kommt der berechnete Wert in meine Datenbank.BlackJack hat geschrieben:Mal sehen ob ich's richtig verstanden habe: Aus den Daten willst alle Flächenwerte mit gleichem Namen und gleicher Jahreszahl aufaddieren und dann pro Namen jeweils das Jahr mit der grössten Fläche wissen!?
Also aufaddieren im Beispiel:
Name Fläche Datum
x 23 1996
x 60 2000
y 19 1998
Und Endergebnis dann:
x 2000
y 1998
Wenn die erste Zeile der Ausgangsdaten 'x 58 1996' lauten würde, wäre trotzdem 'x 2000' die richtige Antwort?
Kann man irgendwelche Annahmen über die Reihenfolge der Ausgangsdaten machen? In Deinem Beispiel sind die ja nach Namen und dann nach Jahr sortiert. Zufall?
Wenn die Daten aus der Tabelle nach Namen oder nach Namen und Jahr sortiert sind, geht's ein wenig effizienter.
Tabelle liegt in ner Geodatabase und ich komm da nicht ganz richtig ran. Das Beispiel war nur zur Veranschaulichung. Die sind NICHT nach Jahr, sondern nur nach Name sortiert. Das Beispiel hier ist jetzt nur konstruiert. ...
Also ich habe immer nur einen Namen auf einmal zu handlen, dann ist gut.
defaultdict geht auch nur mit 2.5, oder? Ich bin wegen ArcGis an 2.4 gebunden
Okay, das ganze ohne `defaultdict`:
Code: Alles auswählen
def aggregate_years(table):
result = dict()
for name, area, year in table:
key = (name, year)
result[key] = result.get(key, 0) + area
return ((name, area, year) for (name, year), area in result.iteritems())
def largest_areas(table):
result = dict()
for name, area, year in aggregate_years(table):
result[name] = max(result.get(name, (0, 0)), (area, year))
return dict((name, year) for (name, (area, year)) in result.iteritems())
def main():
table = (('x', 23, 1996),
('x', 4, 2000),
('x', 56, 2000),
('y', 7, 1998),
('y', 12, 1998))
print largest_areas(table) # => {'y': 1998, 'x': 2000}
Und jetzt etwas effizienter für sortierte Namen:
Code: Alles auswählen
from itertools import groupby
from operator import itemgetter
fst = itemgetter(0)
snd = itemgetter(1)
def max_area_year(table):
result = dict()
for dummy, area, year in table:
result[year] = result.get(year, 0) + area
return snd(max((area, year) for year, area in result.iteritems()))
def largest_areas(table):
return ((name, max_area_year(group)) for name, group in groupby(table, fst))
def main():
table = (('x', 23, 1996),
('x', 4, 2000),
('x', 56, 2000),
('y', 7, 1998),
('y', 12, 1998))
print list(largest_areas(table)) # => [('x', 2000), ('y', 1998)]
okay, also wenn ich das richtig verstanden habe:
groupby fasst gleiche Listeneinträge zusammen, für einen Vorgegebenen Key:
Praktisch in dem Fall für das Jahr, weil ich das als Key festgelegt habe (mit dem snd). Und das 1. Argument gibt an, welche Liste gruppiert werden soll?
groupby fasst gleiche Listeneinträge zusammen, für einen Vorgegebenen Key:
Code: Alles auswählen
In [32]: for group in groupby(table, snd):
....: print group
....:
....:
(1996, <itertools._grouper object at 0x00A9D0C0>)
(2000, <itertools._grouper object at 0x00A9D120>)
(1998, <itertools._grouper object at 0x00A9D0C0>)
Fast richtig. Es werden gleiche ("gleich" nach Schlüsselfunktion) *aufeinanderfolgende* Elemente zusammengefasst. Wenn die Ausgangsdaten nicht nach Jahr sortiert sind kann das gleiche Jahr öfter vorkommen. Darum fragte ich ja weiter oben wie die Daten sortiert sind.
achso .... okay...
ABER, wenn ich vorher schon mit einer for schleife durch meine Tabelle laufe und dann mit Hilfe von takewhile und dropwhile am Ende eh nur die Fälle habe, wo name = (also z.B name NUR x) .... dann brauch ich ja theoretisch nur die 1. Funktion max_area_year.
(Sorry, wie gesagt, ich lerne das alles noch und brauch wahrscheinlich einen Moment länger, bevor es vollkommen klick macht)
ich hab praktisch ein neues leeres dictionary angelegt, was da heißt result, in das ich nun für jeden Listeneintrag in table einen Eintrag mache, Schlüssel lege ich year fest und da es pro Jahr mehrere Einträge gibt, wird für einen gleichen Year eintrag die Fläche einach aufsummiert?
ABER, wenn ich vorher schon mit einer for schleife durch meine Tabelle laufe und dann mit Hilfe von takewhile und dropwhile am Ende eh nur die Fälle habe, wo name = (also z.B name NUR x) .... dann brauch ich ja theoretisch nur die 1. Funktion max_area_year.
(Sorry, wie gesagt, ich lerne das alles noch und brauch wahrscheinlich einen Moment länger, bevor es vollkommen klick macht)
Code: Alles auswählen
for dummy, area, year in table:
result[year] = result.get(year, 0) + area
wenn ich das einzeln auseinander nehmen (also versuche gerade das im Detail alles einzeln zu verstehen, was was zurückgibt):
warum wird da ein False ausgegeben,
hier aber nicht?
Code: Alles auswählen
In [108]: year, area in result.iteritems()
Out[108]: (2000, False)
Code: Alles auswählen
In [109]: for year, area in result.iteritems():
.....: print year, area
.....:
.....:
2000 6790.5
2001 6789.67
Weilmeneliel hat geschrieben:warum wird da ein False ausgegeben,Code: Alles auswählen
In [108]: year, area in result.iteritems() Out[108]: (2000, False)
hier aber nicht?Code: Alles auswählen
In [109]: for year, area in result.iteritems(): .....: print year, area .....: .....: 2000 6790.5 2001 6789.67
Code: Alles auswählen
year, area in result.iteritems()
Code: Alles auswählen
(year, (area in result.iteritems())
Code: Alles auswählen
for year, area in result.iteritems():
Code: Alles auswählen
for (year, area) in result.iteritems():
BeeWee