Forum: PC-Programmierung Python: json Datei lesen und Objekte plotten


von Andi (Gast)


Lesenswert?

Hallo zusammen,

ich bin neu mit python unterwegs und habe eigentlich eine recht simple 
Aufgabe vor mir (habe ich gedacht).

Ich habe ein json File mit verschiedenen Keys Obejekten und möchte diese 
plotten.
1
import numpy as np
2
import matplotlib.pyplot as plt

Ich erstelle mir ein def zum plotten
1
def chart_plot(x,y):
2
    plt.plot(x,y)
3
    plt.grid(True)
4
    plt.ylabel('wert')
5
    plt.xlabel('time')
6
    plt.show()

Ich lade also die json:
1
chart = json.loads(open('base.json').read())

Dann soll er die numpy arrays solange füllen, wie es die Anzahl der 
Zeitstempel (key date) vorgibt.
1
for i in range(0,len(chart['date'])):
2
        x = np.array(chart['date'])
3
        y = np.array(chart['wert'])
4
    chart_plot(x,y)

Leider kommt immer ein Fehler:
1
TypeError: list indices must be integers or slices, not str

Ich habe echt alles versucht.
Habe es sogar über pandas und dataframe versucht, mit dem gleichen 
Ergebnis/Fehler.

Kann mir jemand sagen, wo mein Fehler ist bzw kann mir ein einfaches Bsp 
zeigen, wie ich eine json auslese und zwei Objekte davon in einem 
x-y-Diagramm plotten kann?

Ich dachte die Aufgabe ist einfach, aber auch nach 2h komme ich nicht 
zum Ziel.

Vielen Dank!
Andi :)

von Florian F. (flof3000)


Lesenswert?

Dein chart ist kein dict sondern eine Liste. Mach doch Mal Print chart 
um zu sehen was eingelesen wird.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Zeig mal deine JSON-Datei.

Bei mir funktioniert dein Code mit folgendem Inhalt von base.json:

1
{
2
  "date": [ 1, 2, 4, 8 ],
3
  "wert": [ 1.1, 2.2, 3.3, 4.4 ]
4
}

Die Zeile

1
for i in range(0,len(chart['date'])):

kannst du dir sparen. Das Programm funktioniert zwar auch mit ihr,
befüllt die Array x und y aber unsinnigerweise mehrmals.

Die Zeilen

1
x = np.array(chart['date'])
2
y = np.array(chart['wert'])

befüllen jeweils das komplette Array, und mehr willst du wahrscheinlich
nicht.

von Andi (Gast)


Lesenswert?

Chart hat genau den Inhalt der json Datei.
Print(Chart) gibt in der Ausgabe das aus, was man auch in einem Editor 
sehen würde.

An anderer Stelle funktioniert der Zugriff auf die Objekte aber auf 
diese Art und Weise... Mhm...

von Sheeva P. (sheevaplug)


Lesenswert?

Andi schrieb:
> Chart hat genau den Inhalt der json Datei.
> Print(Chart) gibt in der Ausgabe das aus, was man auch in einem Editor
> sehen würde.

Jetzt wissen wir immer noch nicht, wie Deine JSON-Datei aussieht. Aber 
um Deine Frage zu beantworten, wäre dieses Wissen essentiell.

von Andi (Gast)


Lesenswert?

Die json sieht bei mir etwas anders aus:
1
[{"date":12345,"wert":6789},{"date":23456,"wert":2763}]

Die Klammern sind also etwas anders... Aber das sollte dem Finden der 
Keys doch keinen Abbruch tun?

Vielen Dank!
Andi

von Sheeva P. (sheevaplug)


Lesenswert?

Andi schrieb:
> Die json sieht bei mir etwas anders aus:
>
1
> [{"date":12345,"wert":6789},{"date":23456,"wert":2763}]
2
>
>
> Die Klammern sind also etwas anders... Aber das sollte dem Finden der
> Keys doch keinen Abbruch tun?

Doch, natürlich. Was Du da hast, ist eine Liste von Dictionaries. Auf 
die Liste kannst Du nur mit Integer-Indices zugreifen. Was Du also 
machen willst, ist:
1
meineListe = [{"date":12345,"wert":6789},{"date":23456,"wert":2763}]
2
x = [e['date'] for e in meineListe]
3
y = [e['wert'] for e in meineListe]

oder etwas langsamer, dafür mehr Möglichkeiten die Daten "on the fly" zu 
manipulieren:
1
meineListe = [{"date":12345,"wert":6789},{"date":23456,"wert":2763}]
2
x, y = list(), list()
3
for e in meineListe:
4
  x.append(e['date'])
5
  y.append(e['wert'])

oder, wie vor:
1
meineListe = [{"date":12345,"wert":6789},{"date":23456,"wert":2763}]
2
x = map(lambda e: e['date'], d)
3
y = map(lambda e: e['wert'], d)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Oder als Einzeiler ohne List-Comprehension und mit nur einem Lambda
(dieses zu eliminieren würde den Ausdruck stark in die Länge ziehen):
1
chart_plot(*zip(*map(lambda d:map(d.get,['date','wert']),json.load(open('base.json')))))

von Andi (Gast)


Lesenswert?

Vielen herzlichen Dank!

Sheeva P. schrieb:
> meineListe = [{"date":12345,"wert":6789},{"date":23456,"wert":2763}]
> x = [e['date'] for e in meineListe]
> y = [e['wert'] for e in meineListe]

Wie kann ich in diesen Plot eine einfache rote Linie plotten mit einem 
float Wert?
Offenbar sind x unx y nicht mit int/float in einem Plot vereinbar...

Vielen Dank!
Andi

von Sheeva P. (sheevaplug)


Lesenswert?

Andi schrieb:
> Wie kann ich in diesen Plot eine einfache rote Linie plotten mit einem
> float Wert?
> Offenbar sind x unx y nicht mit int/float in einem Plot vereinbar...

Aber ja doch:
1
from matplotlib import pyplot as plt
2
import dateutil.parser
3
4
# statt json.load()...
5
d = [{'date': '2017-01-01', 'wert': 5}, 
6
     {'date': '2017-02-01', 'wert': 4}, 
7
     {'date': '2017-03-01', 'wert': 5},
8
     {'date': '2017-04-01', 'wert': 6},
9
     {'date': '2017-05-01', 'wert': 6}]
10
11
x = [dateutil.parser.parse(e['date']) for e in d]
12
y1 = [e['wert'] for e in d]
13
y2 = len(y1) * [4.4]
14
15
plt.plot(x, y1)
16
plt.plot(x, y2, 'r')
17
plt.show()

Ach so, kleiner Hinweis am Rande: matplotlib ist eine leistungsfähige 
und IIRC an Matlab angelehnte Python-Library, und daher wahrscheinlich 
keine besonders gute Übung für den Einstieg ist. Auch wenn Du gerade 
Dein ganz konkretes Problem lösen möchtest, erscheint es mir 
zielführender, zuerst einmal die Grundzüge der Sprache zu erwerben: 
Datentypen wie Listen und Dictionaries, List- und Dict-Comprehensions, 
die Builtinfunktionen sowie vielleicht eine kleine Tour durch die 
Standardmodule. YMMV. ;-)

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.