In [132]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

Get weather data

Darksky data

https://darksky.net/

https://github.com/lukaskubis/darkskylib

pip install darkskylib

In [133]:
# Load the API key for darksky
with open('darksky_key.txt') as f:
    key = f.read()

In [134]:
from darksky import forecast

In [135]:
coords_grenoble = ( 45.166672, 5.71667 ) 

data = forecast(key, *coords_grenoble, units='si', lang='fr' )

In [136]:
type( data )


Out[136]:
darksky.forecast.Forecast

In [137]:
data['currently']['temperature']


Out[137]:
15.39

In [138]:
len( data['daily']['data'] )


Out[138]:
8

In [139]:
T = [ hour.temperature for hour in data.hourly ]

print( len(T) )


49

In [140]:
plt.plot( T )


Out[140]:
[<matplotlib.lines.Line2D at 0x7fbbe7a7e470>]

In [141]:
from datetime import datetime as dt

In [150]:
t = dt(2017, 6, 10).isoformat()  # year month day hour ...

In [151]:
exclude = ['currently', 'minutely', 'daily', 'flags']
data = forecast(key, *coords_grenoble, units='si', lang='fr', time=t, exclude=exclude)

In [152]:
records = data['hourly']['data']

In [153]:
records


Out[153]:
[{'apparentTemperature': 16.69,
  'cloudCover': 0.91,
  'dewPoint': 12.41,
  'humidity': 0.76,
  'icon': 'partly-cloudy-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.14,
  'summary': 'Nuageux',
  'temperature': 16.69,
  'time': 1497045600,
  'uvIndex': 0,
  'visibility': 14.47,
  'windBearing': 34,
  'windSpeed': 0.32},
 {'apparentTemperature': 16.06,
  'cloudCover': 0.75,
  'dewPoint': 12.58,
  'humidity': 0.8,
  'icon': 'partly-cloudy-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.26,
  'summary': 'Nuageux',
  'temperature': 16.06,
  'time': 1497049200,
  'uvIndex': 0,
  'visibility': 14.47,
  'windBearing': 38,
  'windSpeed': 0.57},
 {'apparentTemperature': 15.13,
  'cloudCover': 0.52,
  'dewPoint': 12.13,
  'humidity': 0.82,
  'icon': 'partly-cloudy-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.38,
  'summary': 'Nuages Épars',
  'temperature': 15.13,
  'time': 1497052800,
  'uvIndex': 0,
  'visibility': 13,
  'windBearing': 8,
  'windSpeed': 0.8},
 {'apparentTemperature': 15.24,
  'cloudCover': 0.64,
  'dewPoint': 12.49,
  'humidity': 0.84,
  'icon': 'partly-cloudy-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.49,
  'summary': 'Nuageux',
  'temperature': 15.24,
  'time': 1497056400,
  'uvIndex': 0,
  'visibility': 12.38,
  'windBearing': 11,
  'windSpeed': 0.72},
 {'apparentTemperature': 14.49,
  'cloudCover': 0.7,
  'dewPoint': 11.93,
  'humidity': 0.85,
  'icon': 'partly-cloudy-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.6,
  'summary': 'Nuageux',
  'temperature': 14.49,
  'time': 1497060000,
  'uvIndex': 0,
  'visibility': 11.68,
  'windBearing': 14,
  'windSpeed': 0.65},
 {'apparentTemperature': 13.91,
  'cloudCover': 0.8,
  'dewPoint': 11.73,
  'humidity': 0.87,
  'icon': 'partly-cloudy-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.71,
  'summary': 'Nuageux',
  'temperature': 13.91,
  'time': 1497063600,
  'uvIndex': 0,
  'visibility': 14.65,
  'windBearing': 13,
  'windSpeed': 0.55},
 {'apparentTemperature': 13.8,
  'cloudCover': 0.31,
  'dewPoint': 11.82,
  'humidity': 0.88,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1019,
  'summary': 'Nuages Épars',
  'temperature': 13.8,
  'time': 1497067200,
  'uvIndex': 0,
  'visibility': 14.13,
  'windBearing': 8,
  'windSpeed': 0.42},
 {'apparentTemperature': 14.94,
  'cloudCover': 0.52,
  'dewPoint': 12.58,
  'humidity': 0.86,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0.1041,
  'precipProbability': 0.17,
  'precipType': 'rain',
  'pressure': 1019.43,
  'summary': 'Nuages Épars',
  'temperature': 14.94,
  'time': 1497070800,
  'uvIndex': 0,
  'visibility': 11.68,
  'windBearing': 9,
  'windSpeed': 1.36},
 {'apparentTemperature': 17.92,
  'cloudCover': 0.52,
  'dewPoint': 13.21,
  'humidity': 0.74,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1019.79,
  'summary': 'Nuages Épars',
  'temperature': 17.92,
  'time': 1497074400,
  'uvIndex': 1,
  'visibility': 12.33,
  'windBearing': 0,
  'windSpeed': 1.76},
 {'apparentTemperature': 20.42,
  'cloudCover': 0.31,
  'dewPoint': 13.43,
  'humidity': 0.64,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1019.67,
  'summary': 'Nuages Épars',
  'temperature': 20.42,
  'time': 1497078000,
  'uvIndex': 1,
  'visibility': 13.95,
  'windBearing': 8,
  'windSpeed': 1.18},
 {'apparentTemperature': 21.19,
  'cloudCover': 0.31,
  'dewPoint': 12.45,
  'humidity': 0.57,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1019.46,
  'summary': 'Nuages Épars',
  'temperature': 21.19,
  'time': 1497081600,
  'uvIndex': 3,
  'visibility': 16.09,
  'windBearing': 358,
  'windSpeed': 1.18},
 {'apparentTemperature': 23.46,
  'cloudCover': 0.31,
  'dewPoint': 12.94,
  'humidity': 0.52,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1019.09,
  'summary': 'Nuages Épars',
  'temperature': 23.46,
  'time': 1497085200,
  'uvIndex': 4,
  'visibility': 12.92,
  'windBearing': 347,
  'windSpeed': 2.06},
 {'apparentTemperature': 24.66,
  'cloudCover': 0.31,
  'dewPoint': 13.71,
  'humidity': 0.51,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.67,
  'summary': 'Nuages Épars',
  'temperature': 24.66,
  'time': 1497088800,
  'uvIndex': 6,
  'visibility': 12.01,
  'windBearing': 345,
  'windSpeed': 2.41},
 {'apparentTemperature': 26.01,
  'cloudCover': 0.31,
  'dewPoint': 14.02,
  'humidity': 0.48,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.05,
  'summary': 'Nuages Épars',
  'temperature': 26.01,
  'time': 1497092400,
  'uvIndex': 8,
  'visibility': 12.94,
  'windBearing': 341,
  'windSpeed': 2.12},
 {'apparentTemperature': 27.07,
  'cloudCover': 0.31,
  'dewPoint': 13.86,
  'humidity': 0.45,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1017.64,
  'summary': 'Nuages Épars',
  'temperature': 26.96,
  'time': 1497096000,
  'uvIndex': 8,
  'visibility': 14,
  'windBearing': 346,
  'windSpeed': 1.79},
 {'apparentTemperature': 27.41,
  'cloudCover': 0.31,
  'dewPoint': 12.97,
  'humidity': 0.41,
  'icon': 'partly-cloudy-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1016.99,
  'summary': 'Nuages Épars',
  'temperature': 27.41,
  'time': 1497099600,
  'uvIndex': 7,
  'visibility': 14.63,
  'windBearing': 339,
  'windSpeed': 1.94},
 {'apparentTemperature': 28.22,
  'dewPoint': 13.49,
  'humidity': 0.4,
  'icon': 'clear-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1016.66,
  'summary': 'Dégagé',
  'temperature': 28.22,
  'time': 1497103200,
  'visibility': 14.63,
  'windBearing': 328,
  'windSpeed': 1.96},
 {'apparentTemperature': 28.22,
  'dewPoint': 13.38,
  'humidity': 0.4,
  'icon': 'clear-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1016.41,
  'summary': 'Dégagé',
  'temperature': 28.22,
  'time': 1497106800,
  'visibility': 16.09,
  'windBearing': 350,
  'windSpeed': 2.2},
 {'apparentTemperature': 28.16,
  'dewPoint': 13.6,
  'humidity': 0.41,
  'icon': 'clear-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1016.21,
  'summary': 'Dégagé',
  'temperature': 28.16,
  'time': 1497110400,
  'visibility': 16.09,
  'windBearing': 351,
  'windSpeed': 2.87},
 {'apparentTemperature': 27.73,
  'dewPoint': 13.93,
  'humidity': 0.43,
  'icon': 'clear-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1016.3,
  'summary': 'Dégagé',
  'temperature': 27.73,
  'time': 1497114000,
  'visibility': 16.09,
  'windBearing': 6,
  'windSpeed': 2.62},
 {'apparentTemperature': 26.12,
  'dewPoint': 13.82,
  'humidity': 0.47,
  'icon': 'clear-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1016.55,
  'summary': 'Dégagé',
  'temperature': 26.12,
  'time': 1497117600,
  'visibility': 16.09,
  'windBearing': 358,
  'windSpeed': 2.69},
 {'apparentTemperature': 22.98,
  'dewPoint': 14.25,
  'humidity': 0.58,
  'icon': 'clear-day',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1017.08,
  'summary': 'Dégagé',
  'temperature': 22.98,
  'time': 1497121200,
  'visibility': 16.09,
  'windBearing': 327,
  'windSpeed': 0.77},
 {'apparentTemperature': 21.21,
  'dewPoint': 14.22,
  'humidity': 0.64,
  'icon': 'clear-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1017.81,
  'summary': 'Dégagé',
  'temperature': 21.21,
  'time': 1497124800,
  'visibility': 15.06,
  'windBearing': 356,
  'windSpeed': 0.9},
 {'apparentTemperature': 19.61,
  'dewPoint': 14.23,
  'humidity': 0.71,
  'icon': 'clear-night',
  'precipIntensity': 0,
  'precipProbability': 0,
  'pressure': 1018.52,
  'summary': 'Dégagé',
  'temperature': 19.61,
  'time': 1497128400,
  'visibility': 16.09,
  'windBearing': 15,
  'windSpeed': 0.61}]

In [154]:
dropcols = ['icon', 'apparentTemperature', 'ozone', 'summary', 'uvIndex', 'windGust', 'dewPoint',
               'precipProbability', 'visibility', 'pressure', 'humidity', 'precipType']

In [155]:
df = pd.DataFrame.from_records(records, index='time')

df.drop(dropcols, axis=1, level=None, inplace=True, errors='ignore')

In [156]:
len(records)


Out[156]:
24

In [100]:
df.index = pd.to_datetime(df.index ,unit='s')

In [101]:
df


Out[101]:
cloudCover precipIntensity temperature windBearing windSpeed
time
2017-06-16 22:00:00 NaN 0 19.65 338 1.30
2017-06-16 23:00:00 NaN 0 18.34 355 3.56
2017-06-17 00:00:00 NaN 0 18.02 12 2.24
2017-06-17 01:00:00 NaN 0 16.92 4 2.87
2017-06-17 02:00:00 NaN 0 16.42 0 1.77
2017-06-17 03:00:00 NaN 0 16.57 358 2.11
2017-06-17 04:00:00 NaN 0 15.44 352 2.11
2017-06-17 05:00:00 NaN 0 16.06 353 1.30
2017-06-17 06:00:00 0.31 0 18.16 356 2.01
2017-06-17 07:00:00 NaN 0 19.86 353 3.55
2017-06-17 08:00:00 0.31 0 20.86 3 5.05
2017-06-17 09:00:00 NaN 0 22.63 5 5.74
2017-06-17 10:00:00 NaN 0 23.68 6 5.76
2017-06-17 11:00:00 NaN 0 25.17 356 5.61
2017-06-17 12:00:00 NaN 0 25.90 358 5.51
2017-06-17 13:00:00 NaN 0 26.66 0 5.95
2017-06-17 14:00:00 0.31 0 27.18 353 6.41
2017-06-17 15:00:00 0.31 0 27.62 4 6.16
2017-06-17 16:00:00 0.31 0 27.35 0 6.09
2017-06-17 17:00:00 0.31 0 26.74 3 6.10
2017-06-17 18:00:00 0.31 0 25.43 354 5.15
2017-06-17 19:00:00 0.31 0 23.24 355 2.95
2017-06-17 20:00:00 0.31 0 21.51 4 2.36
2017-06-17 21:00:00 NaN 0 19.69 5 3.07

In [29]:
T = [ hour.temperature for hour in data.hourly ]

print( len(T) )


24

In [11]:
di = [{'t':45, 'value':4}, {'t':78, 'value':77}]

In [12]:
import pandas as pd

In [14]:
plt.plot( T );



In [15]:
windSpeed = [ hour.windSpeed for hour in data.hourly ]

plt.plot( windSpeed );



In [16]:
cloudCover = [ hour.cloudCover for hour in data.hourly ]

plt.plot( cloudCover );



In [26]:
data.hourly[4].temperature


Out[26]:
20.06

In [27]:
timeindex = pd.to_datetime('today')[ hour.time for hour in data.hourly ]


Out[27]:
[1498168800,
 1498172400,
 1498176000,
 1498179600,
 1498183200,
 1498186800,
 1498190400,
 1498194000,
 1498197600,
 1498201200,
 1498204800,
 1498208400,
 1498212000,
 1498215600,
 1498219200,
 1498222800,
 1498226400,
 1498230000,
 1498233600,
 1498237200,
 1498240800,
 1498244400,
 1498248000,
 1498251600]

In [30]:
[ hour['temperature'] for hour in data.hourly ]


Out[30]:
[21.54,
 21.07,
 22.03,
 21.08,
 20.06,
 20.44,
 21.89,
 24.05,
 25.83,
 27.32,
 28.54,
 29.4,
 30.21,
 30.89,
 32.4,
 33.06,
 33.38,
 32.55,
 32.17,
 31.39,
 30.11,
 28.49,
 26.26,
 24.19]

In [54]:
import pandas as pd

In [61]:
# voir https://darksky.net/dev/docs/response
datalabels = ['temperature', 'cloudCover', 'precipIntensity', 'windSpeed' , 'windBearing']

In [66]:
def buildDFdaily(day, coords):
    data = forecast(key, *coords, units='si', lang='fr', time=day)
    
    timeindex = pd.to_datetime( [ hour.time for hour in data.hourly ],  unit='s' , origin='unix' )
    
    dailydata = {}
    for label in datalabels:
        dailydata[label] = [ dataeveryhour[label] for dataeveryhour in data.hourly ]
        
    df = pd.DataFrame(dailydata, index=timeindex )
    return df

In [67]:
df = buildDFdaily( t, coords_grenoble )

In [68]:
df


Out[68]:
cloudCover precipIntensity temperature windBearing windSpeed
2017-06-22 22:00:00 0.15 0.0000 21.54 145 0.82
2017-06-22 23:00:00 0.28 0.0000 21.07 134 0.83
2017-06-23 00:00:00 0.40 0.0000 22.03 108 0.78
2017-06-23 01:00:00 0.59 0.0000 21.08 105 0.82
2017-06-23 02:00:00 0.80 0.0000 20.06 106 0.88
2017-06-23 03:00:00 0.92 0.0000 20.44 108 0.89
2017-06-23 04:00:00 0.88 0.0000 21.89 113 0.81
2017-06-23 05:00:00 0.75 0.0000 24.05 119 0.69
2017-06-23 06:00:00 0.64 0.0000 25.83 165 0.24
2017-06-23 07:00:00 0.58 0.0000 27.32 95 0.48
2017-06-23 08:00:00 0.54 0.0000 28.54 25 0.98
2017-06-23 09:00:00 0.50 0.0000 29.40 340 1.26
2017-06-23 10:00:00 0.49 0.0000 30.21 326 1.34
2017-06-23 11:00:00 0.49 0.0000 30.89 328 1.39
2017-06-23 12:00:00 0.46 0.0000 32.40 257 0.80
2017-06-23 13:00:00 0.40 0.0000 33.06 197 0.86
2017-06-23 14:00:00 0.33 0.0000 33.38 13 1.14
2017-06-23 15:00:00 0.30 0.0000 32.55 329 1.31
2017-06-23 16:00:00 0.35 0.0000 32.17 324 1.32
2017-06-23 17:00:00 0.43 0.1295 31.39 334 1.27
2017-06-23 18:00:00 0.50 0.2413 30.11 335 1.06
2017-06-23 19:00:00 0.57 0.2413 28.49 337 0.97
2017-06-23 20:00:00 0.65 0.1829 26.26 339 0.88
2017-06-23 21:00:00 0.72 0.1270 24.19 342 0.82

In [60]:
df.plot()


Out[60]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fbb7dc77828>

Debug


In [174]:
import weatherfeed as wf

In [232]:
coords_grenoble = (45.1973288, 5.7139923) #(45.1973288, 5.7103223)

startday, lastday = pd.to_datetime('10/06/2017', format='%d/%m/%Y'), pd.to_datetime('now')
#pd.to_datetime('01/07/2017', format='%d/%m/%Y')

In [233]:
EXCLUDE = [] #[ 'minutely', 'daily', 'flags']  # from the query

COL2DROP = ['icon', 'apparentTemperature', 'ozone', 'uvIndex', 'windGust', 'dewPoint',
               'precipProbability', 'visibility', 'pressure', 'humidity', 'precipType']

coords = coords_grenoble

In [234]:
daterange = pd.date_range(start=startday, end=lastday,  freq='D', normalize=True)
daterange


Out[234]:
DatetimeIndex(['2017-06-10', '2017-06-11', '2017-06-12', '2017-06-13',
               '2017-06-14', '2017-06-15', '2017-06-16', '2017-06-17',
               '2017-06-18', '2017-06-19', '2017-06-20', '2017-06-21',
               '2017-06-22', '2017-06-23', '2017-06-24', '2017-06-25',
               '2017-06-26', '2017-06-27', '2017-06-28', '2017-06-29',
               '2017-06-30', '2017-07-01'],
              dtype='datetime64[ns]', freq='D')

In [235]:
records = []
for day in daterange:

    day_iso = day.isoformat()

    print('%i, '%day.day, end='')

    data = forecast(KEY, *coords, units='si', lang='fr', \
         time=day_iso)
    records_oftheday = data['hourly']['data']
    records.extend( records_oftheday )


10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 

In [236]:
# build DF:
allweatherdata = pd.DataFrame.from_records(records, index='time')
allweatherdata.drop(COL2DROP, axis=1, inplace=True, errors='ignore')

allweatherdata.index = pd.to_datetime(allweatherdata.index ,unit='s')

allweatherdata['cloudCover'] = allweatherdata['cloudCover'].fillna( 0 )

In [237]:
allweatherdata.isnull().sum()


Out[237]:
cloudCover         0
precipIntensity    0
summary            0
temperature        0
windBearing        0
windSpeed          0
dtype: int64

In [240]:
allweatherdata.duplicated()


Out[240]:
time
2017-06-09 22:00:00    False
2017-06-09 23:00:00    False
2017-06-10 00:00:00    False
2017-06-10 01:00:00    False
2017-06-10 02:00:00    False
2017-06-10 03:00:00    False
2017-06-10 04:00:00    False
2017-06-10 05:00:00    False
2017-06-10 06:00:00    False
2017-06-10 07:00:00    False
2017-06-10 08:00:00    False
2017-06-10 09:00:00    False
2017-06-10 10:00:00    False
2017-06-10 11:00:00    False
2017-06-10 12:00:00    False
2017-06-10 13:00:00    False
2017-06-10 14:00:00    False
2017-06-10 15:00:00    False
2017-06-10 16:00:00    False
2017-06-10 17:00:00    False
2017-06-10 18:00:00    False
2017-06-10 19:00:00    False
2017-06-10 20:00:00    False
2017-06-10 21:00:00    False
2017-06-10 22:00:00    False
2017-06-10 23:00:00    False
2017-06-11 00:00:00    False
2017-06-11 01:00:00    False
2017-06-11 02:00:00    False
2017-06-11 03:00:00    False
                       ...  
2017-06-30 16:00:00    False
2017-06-30 17:00:00    False
2017-06-30 18:00:00    False
2017-06-30 19:00:00    False
2017-06-30 20:00:00    False
2017-06-30 21:00:00    False
2017-06-30 22:00:00    False
2017-06-30 23:00:00    False
2017-07-01 00:00:00    False
2017-07-01 01:00:00    False
2017-07-01 02:00:00    False
2017-07-01 03:00:00    False
2017-07-01 04:00:00    False
2017-07-01 05:00:00    False
2017-07-01 06:00:00    False
2017-07-01 07:00:00    False
2017-07-01 08:00:00    False
2017-07-01 09:00:00    False
2017-07-01 10:00:00    False
2017-07-01 11:00:00    False
2017-07-01 12:00:00    False
2017-07-01 13:00:00    False
2017-07-01 14:00:00    False
2017-07-01 15:00:00    False
2017-07-01 16:00:00    False
2017-07-01 17:00:00    False
2017-07-01 18:00:00    False
2017-07-01 19:00:00    False
2017-07-01 20:00:00    False
2017-07-01 21:00:00    False
Length: 528, dtype: bool

In [239]:
allweatherdata.plot( )


Out[239]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fbbe7fa3b00>

In [164]:
data


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/Projets/thermique_appart/py3/lib/python3.5/site-packages/IPython/core/formatters.py in __call__(self, obj)
    691                 type_pprinters=self.type_printers,
    692                 deferred_pprinters=self.deferred_printers)
--> 693             printer.pretty(obj)
    694             printer.flush()
    695             return stream.getvalue()

~/Projets/thermique_appart/py3/lib/python3.5/site-packages/IPython/lib/pretty.py in pretty(self, obj)
    378                             if callable(meth):
    379                                 return meth(obj, self, cycle)
--> 380             return _default_pprint(obj, self, cycle)
    381         finally:
    382             self.end_group()

~/Projets/thermique_appart/py3/lib/python3.5/site-packages/IPython/lib/pretty.py in _default_pprint(obj, p, cycle)
    493     if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
    494         # A user-provided repr. Find newlines and replace them with p.break_()
--> 495         _repr_pprint(obj, p, cycle)
    496         return
    497     p.begin_group(1, '<')

~/Projets/thermique_appart/py3/lib/python3.5/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
    691     """A pprint that just redirects to the normal repr function."""
    692     # Find newlines and replace them with p.break_()
--> 693     output = repr(obj)
    694     for idx,output_line in enumerate(output.splitlines()):
    695         if idx:

TypeError: __repr__ returned non-string (type dict)

In [ ]: