1&&\"string\"==typeof v&&!d.checkClone&&De.test(v))return e.each((function(i){var o=e.eq(i);y&&(t[0]=v.call(this,i,o.html())),Re(o,t,n,r)}));if(p&&(a=(i=xe(t,e[0].ownerDocument,!1,e,r)).firstChild,1===i.childNodes.length&&(i=a),a||r)){for(u=(s=b.map(ve(i,\"script\"),Le)).length;f0&&ye(a,!u&&ve(e,\"script\")),s},cleanData:function(e){for(var t,n,r,i=b.event.special,o=0;void 0!==(n=e[o]);o++)if(X(n)){if(t=n[G.expando]){if(t.events)for(r in t.events)i[r]?b.event.remove(n,r):b.removeEvent(n,r,t.handle);n[G.expando]=void 0}n[Y.expando]&&(n[Y.expando]=void 0)}}}),b.fn.extend({detach:function(e){return Me(this,e,!0)},remove:function(e){return Me(this,e)},text:function(e){return B(this,(function(e){return void 0===e?b.text(this):this.empty().each((function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)}))}),null,e,arguments.length)},append:function(){return Re(this,arguments,(function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||qe(this,e).appendChild(e)}))},prepend:function(){return Re(this,arguments,(function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=qe(this,e);t.insertBefore(e,t.firstChild)}}))},before:function(){return Re(this,arguments,(function(e){this.parentNode&&this.parentNode.insertBefore(e,this)}))},after:function(){return Re(this,arguments,(function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)}))},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(b.cleanData(ve(e,!1)),e.textContent=\"\");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map((function(){return b.clone(this,e,t)}))},html:function(e){return B(this,(function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if(\"string\"==typeof e&&!Ne.test(e)&&!ge[(de.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=b.htmlPrefilter(e);try{for(;n3,ne.removeChild(t)),s}}))}();var ze=[\"Webkit\",\"Moz\",\"ms\"],Ue=v.createElement(\"div\").style,Xe={};function Ve(e){var t=b.cssProps[e]||Xe[e];return t||(e in Ue?e:Xe[e]=function(e){for(var t=e[0].toUpperCase()+e.slice(1),n=ze.length;n--;)if((e=ze[n]+t)in Ue)return e}(e)||e)}var Ge=/^(none|table(?!-c[ea]).+)/,Ye=/^--/,Qe={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Je={letterSpacing:\"0\",fontWeight:\"400\"};function Ke(e,t,n){var r=ee.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||\"px\"):t}function Ze(e,t,n,r,i,o){var a=\"width\"===t?1:0,s=0,u=0;if(n===(r?\"border\":\"content\"))return 0;for(;a<4;a+=2)\"margin\"===n&&(u+=b.css(e,n+te[a],!0,i)),r?(\"content\"===n&&(u-=b.css(e,\"padding\"+te[a],!0,i)),\"margin\"!==n&&(u-=b.css(e,\"border\"+te[a]+\"Width\",!0,i))):(u+=b.css(e,\"padding\"+te[a],!0,i),\"padding\"!==n?u+=b.css(e,\"border\"+te[a]+\"Width\",!0,i):s+=b.css(e,\"border\"+te[a]+\"Width\",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e[\"offset\"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function et(e,t,n){var r=We(e),i=(!d.boxSizingReliable()||n)&&\"border-box\"===b.css(e,\"boxSizing\",!1,r),o=i,a=$e(e,t,r),s=\"offset\"+t[0].toUpperCase()+t.slice(1);if(Ie.test(a)){if(!n)return a;a=\"auto\"}return(!d.boxSizingReliable()&&i||!d.reliableTrDimensions()&&k(e,\"tr\")||\"auto\"===a||!parseFloat(a)&&\"inline\"===b.css(e,\"display\",!1,r))&&e.getClientRects().length&&(i=\"border-box\"===b.css(e,\"boxSizing\",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ze(e,t,n||(i?\"border\":\"content\"),o,r,a)+\"px\"}function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=$e(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=U(t),u=Ye.test(t),l=e.style;if(u||(t=Ve(s)),a=b.cssHooks[t]||b.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];\"string\"===(o=typeof n)&&(i=ee.exec(n))&&i[1]&&(n=ae(e,t,i),o=\"number\"),null!=n&&n==n&&(\"number\"!==o||u||(n+=i&&i[3]||(b.cssNumber[s]?\"\":\"px\")),d.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(l[t]=\"inherit\"),a&&\"set\"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=U(t);return Ye.test(t)||(t=Ve(s)),(a=b.cssHooks[t]||b.cssHooks[s])&&\"get\"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=$e(e,t,r)),\"normal\"===i&&t in Je&&(i=Je[t]),\"\"===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),b.each([\"height\",\"width\"],(function(e,t){b.cssHooks[t]={get:function(e,n,r){if(n)return!Ge.test(b.css(e,\"display\"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):Fe(e,Qe,(function(){return et(e,t,r)}))},set:function(e,n,r){var i,o=We(e),a=!d.scrollboxSize()&&\"absolute\"===o.position,s=(a||r)&&\"border-box\"===b.css(e,\"boxSizing\",!1,o),u=r?Ze(e,t,r,s,o):0;return s&&a&&(u-=Math.ceil(e[\"offset\"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,\"border\",!1,o)-.5)),u&&(i=ee.exec(n))&&\"px\"!==(i[3]||\"px\")&&(e.style[t]=n,n=b.css(e,t)),Ke(0,n,u)}}})),b.cssHooks.marginLeft=_e(d.reliableMarginLeft,(function(e,t){if(t)return(parseFloat($e(e,\"marginLeft\"))||e.getBoundingClientRect().left-Fe(e,{marginLeft:0},(function(){return e.getBoundingClientRect().left})))+\"px\"})),b.each({margin:\"\",padding:\"\",border:\"Width\"},(function(e,t){b.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];r<4;r++)i[e+te[r]+t]=o[r]||o[r-2]||o[0];return i}},\"margin\"!==e&&(b.cssHooks[e+t].set=Ke)})),b.fn.extend({css:function(e,t){return B(this,(function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=We(e),i=t.length;a1)}}),b.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||b.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?\"\":\"px\")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=b.css(e.elem,e.prop,\"\"))&&\"auto\"!==t?t:0},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):1!==e.elem.nodeType||!b.cssHooks[e.prop]&&null==e.elem.style[Ve(e.prop)]?e.elem[e.prop]=e.now:b.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},b.fx=tt.prototype.init,b.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===v.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,b.fx.interval),b.fx.tick())}function st(){return e.setTimeout((function(){nt=void 0})),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i[\"margin\"+(n=te[r])]=i[\"padding\"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(ct.tweeners[t]||[]).concat(ct.tweeners[\"*\"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each((function(){b.removeAttr(this,e)}))}}),b.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===e.getAttribute?b.prop(e,t,n):(1===o&&b.isXMLDoc(e)||(i=b.attrHooks[t.toLowerCase()]||(b.expr.match.bool.test(t)?ft:void 0)),void 0!==n?null===n?void b.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:null==(r=b.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!d.radioValue&&\"radio\"===t&&k(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(O);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),ft={set:function(e,t,n){return!1===t?b.removeAttr(e,n):e.setAttribute(n,n),n}},b.each(b.expr.match.bool.source.match(/\\w+/g),(function(e,t){var n=pt[t]||b.find.attr;pt[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=pt[a],pt[a]=i,i=null!=n(e,t,r)?a:null,pt[a]=o),i}}));var dt=/^(?:input|select|textarea|button)$/i,ht=/^(?:a|area)$/i;function gt(e){return(e.match(O)||[]).join(\" \")}function vt(e){return e.getAttribute&&e.getAttribute(\"class\")||\"\"}function yt(e){return Array.isArray(e)?e:\"string\"==typeof e&&e.match(O)||[]}b.fn.extend({prop:function(e,t){return B(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each((function(){delete this[b.propFix[e]||e]}))}}),b.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&b.isXMLDoc(e)||(t=b.propFix[t]||t,i=b.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=b.find.attr(e,\"tabindex\");return t?parseInt(t,10):dt.test(e.nodeName)||ht.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:\"htmlFor\",class:\"className\"}}),d.optSelected||(b.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),b.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],(function(){b.propFix[this.toLowerCase()]=this})),b.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(h(e))return this.each((function(t){b(this).addClass(e.call(this,t,vt(this)))}));if((t=yt(e)).length)for(;n=this[u++];)if(i=vt(n),r=1===n.nodeType&&\" \"+gt(i)+\" \"){for(a=0;o=t[a++];)r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");i!==(s=gt(r))&&n.setAttribute(\"class\",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(h(e))return this.each((function(t){b(this).removeClass(e.call(this,t,vt(this)))}));if(!arguments.length)return this.attr(\"class\",\"\");if((t=yt(e)).length)for(;n=this[u++];)if(i=vt(n),r=1===n.nodeType&&\" \"+gt(i)+\" \"){for(a=0;o=t[a++];)for(;r.indexOf(\" \"+o+\" \")>-1;)r=r.replace(\" \"+o+\" \",\" \");i!==(s=gt(r))&&n.setAttribute(\"class\",s)}return this},toggleClass:function(e,t){var n=typeof e,r=\"string\"===n||Array.isArray(e);return\"boolean\"==typeof t&&r?t?this.addClass(e):this.removeClass(e):h(e)?this.each((function(n){b(this).toggleClass(e.call(this,n,vt(this),t),t)})):this.each((function(){var t,i,o,a;if(r)for(i=0,o=b(this),a=yt(e);t=a[i++];)o.hasClass(t)?o.removeClass(t):o.addClass(t);else void 0!==e&&\"boolean\"!==n||((t=vt(this))&&G.set(this,\"__className__\",t),this.setAttribute&&this.setAttribute(\"class\",t||!1===e?\"\":G.get(this,\"__className__\")||\"\"))}))},hasClass:function(e){var t,n,r=0;for(t=\" \"+e+\" \";n=this[r++];)if(1===n.nodeType&&(\" \"+gt(vt(n))+\" \").indexOf(t)>-1)return!0;return!1}});var mt=/\\r/g;b.fn.extend({val:function(e){var t,n,r,i=this[0];return arguments.length?(r=h(e),this.each((function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,b(this).val()):e)?i=\"\":\"number\"==typeof i?i+=\"\":Array.isArray(i)&&(i=b.map(i,(function(e){return null==e?\"\":e+\"\"}))),(t=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()])&&\"set\"in t&&void 0!==t.set(this,i,\"value\")||(this.value=i))}))):i?(t=b.valHooks[i.type]||b.valHooks[i.nodeName.toLowerCase()])&&\"get\"in t&&void 0!==(n=t.get(i,\"value\"))?n:\"string\"==typeof(n=i.value)?n.replace(mt,\"\"):null==n?\"\":n:void 0}}),b.extend({valHooks:{option:{get:function(e){var t=b.find.attr(e,\"value\");return null!=t?t:gt(b.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a=\"select-one\"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),b.each([\"radio\",\"checkbox\"],(function(){b.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=b.inArray(b(e).val(),t)>-1}},d.checkOn||(b.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})})),d.focusin=\"onfocusin\"in e;var xt=/^(?:focusinfocus|focusoutblur)$/,bt=function(e){e.stopPropagation()};b.extend(b.event,{trigger:function(t,n,r,i){var o,a,s,u,l,f,p,d,y=[r||v],m=c.call(t,\"type\")?t.type:t,x=c.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(a=d=s=r=r||v,3!==r.nodeType&&8!==r.nodeType&&!xt.test(m+b.event.triggered)&&(m.indexOf(\".\")>-1&&(x=m.split(\".\"),m=x.shift(),x.sort()),l=m.indexOf(\":\")<0&&\"on\"+m,(t=t[b.expando]?t:new b.Event(m,\"object\"==typeof t&&t)).isTrigger=i?2:3,t.namespace=x.join(\".\"),t.rnamespace=t.namespace?new RegExp(\"(^|\\\\.)\"+x.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:b.makeArray(n,[t]),p=b.event.special[m]||{},i||!p.trigger||!1!==p.trigger.apply(r,n))){if(!i&&!p.noBubble&&!g(r)){for(u=p.delegateType||m,xt.test(u+m)||(a=a.parentNode);a;a=a.parentNode)y.push(a),s=a;s===(r.ownerDocument||v)&&y.push(s.defaultView||s.parentWindow||e)}for(o=0;(a=y[o++])&&!t.isPropagationStopped();)d=a,t.type=o>1?u:p.bindType||m,(f=(G.get(a,\"events\")||Object.create(null))[t.type]&&G.get(a,\"handle\"))&&f.apply(a,n),(f=l&&a[l])&&f.apply&&X(a)&&(t.result=f.apply(a,n),!1===t.result&&t.preventDefault());return t.type=m,i||t.isDefaultPrevented()||p._default&&!1!==p._default.apply(y.pop(),n)||!X(r)||l&&h(r[m])&&!g(r)&&((s=r[l])&&(r[l]=null),b.event.triggered=m,t.isPropagationStopped()&&d.addEventListener(m,bt),r[m](),t.isPropagationStopped()&&d.removeEventListener(m,bt),b.event.triggered=void 0,s&&(r[l]=s)),t.result}},simulate:function(e,t,n){var r=b.extend(new b.Event,n,{type:e,isSimulated:!0});b.event.trigger(r,null,t)}}),b.fn.extend({trigger:function(e,t){return this.each((function(){b.event.trigger(e,t,this)}))},triggerHandler:function(e,t){var n=this[0];if(n)return b.event.trigger(e,t,n,!0)}}),d.focusin||b.each({focus:\"focusin\",blur:\"focusout\"},(function(e,t){var n=function(e){b.event.simulate(t,e.target,b.event.fix(e))};b.event.special[t]={setup:function(){var r=this.ownerDocument||this.document||this,i=G.access(r,t);i||r.addEventListener(e,n,!0),G.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this.document||this,i=G.access(r,t)-1;i?G.access(r,t,i):(r.removeEventListener(e,n,!0),G.remove(r,t))}}}));var wt=e.location,Tt={guid:Date.now()},Ct=/\\?/;b.parseXML=function(t){var n;if(!t||\"string\"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,\"text/xml\")}catch(e){n=void 0}return n&&!n.getElementsByTagName(\"parsererror\").length||b.error(\"Invalid XML: \"+t),n};var Et=/\\[\\]$/,St=/\\r?\\n/g,kt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function Nt(e,t,n,r){var i;if(Array.isArray(t))b.each(t,(function(t,i){n||Et.test(e)?r(e,i):Nt(e+\"[\"+(\"object\"==typeof i&&null!=i?t:\"\")+\"]\",i,n,r)}));else if(n||\"object\"!==x(t))r(e,t);else for(i in t)Nt(e+\"[\"+i+\"]\",t[i],n,r)}b.param=function(e,t){var n,r=[],i=function(e,t){var n=h(t)?t():t;r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(null==n?\"\":n)};if(null==e)return\"\";if(Array.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,(function(){i(this.name,this.value)}));else for(n in e)Nt(n,e[n],t,i);return r.join(\"&\")},b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map((function(){var e=b.prop(this,\"elements\");return e?b.makeArray(e):this})).filter((function(){var e=this.type;return this.name&&!b(this).is(\":disabled\")&&At.test(this.nodeName)&&!kt.test(e)&&(this.checked||!pe.test(e))})).map((function(e,t){var n=b(this).val();return null==n?null:Array.isArray(n)?b.map(n,(function(e){return{name:t.name,value:e.replace(St,\"\\r\\n\")}})):{name:t.name,value:n.replace(St,\"\\r\\n\")}})).get()}});var Dt=/%20/g,jt=/#.*$/,qt=/([?&])_=[^&]*/,Lt=/^(.*?):[ \\t]*([^\\r\\n]*)$/gm,Ht=/^(?:GET|HEAD)$/,Ot=/^\\/\\//,Pt={},Rt={},Mt=\"*/\".concat(\"*\"),It=v.createElement(\"a\");function Wt(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(O)||[];if(h(n))for(;r=o[i++];)\"+\"===r[0]?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function Ft(e,t,n,r){var i={},o=e===Rt;function a(s){var u;return i[s]=!0,b.each(e[s]||[],(function(e,s){var l=s(t,n,r);return\"string\"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)})),u}return a(t.dataTypes[0])||!i[\"*\"]&&a(\"*\")}function Bt(e,t){var n,r,i=b.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&b.extend(!0,e,r),e}It.href=wt.href,b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:wt.href,type:\"GET\",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(wt.protocol),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Mt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":JSON.parse,\"text xml\":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Bt(Bt(e,b.ajaxSettings),t):Bt(b.ajaxSettings,e)},ajaxPrefilter:Wt(Pt),ajaxTransport:Wt(Rt),ajax:function(t,n){\"object\"==typeof t&&(n=t,t=void 0),n=n||{};var r,i,o,a,s,u,l,c,f,p,d=b.ajaxSetup({},n),h=d.context||d,g=d.context&&(h.nodeType||h.jquery)?b(h):b.event,y=b.Deferred(),m=b.Callbacks(\"once memory\"),x=d.statusCode||{},w={},T={},C=\"canceled\",E={readyState:0,getResponseHeader:function(e){var t;if(l){if(!a)for(a={};t=Lt.exec(o);)a[t[1].toLowerCase()+\" \"]=(a[t[1].toLowerCase()+\" \"]||[]).concat(t[2]);t=a[e.toLowerCase()+\" \"]}return null==t?null:t.join(\", \")},getAllResponseHeaders:function(){return l?o:null},setRequestHeader:function(e,t){return null==l&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,w[e]=t),this},overrideMimeType:function(e){return null==l&&(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(l)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return r&&r.abort(t),S(0,t),this}};if(y.promise(E),d.url=((t||d.url||wt.href)+\"\").replace(Ot,wt.protocol+\"//\"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=(d.dataType||\"*\").toLowerCase().match(O)||[\"\"],null==d.crossDomain){u=v.createElement(\"a\");try{u.href=d.url,u.href=u.href,d.crossDomain=It.protocol+\"//\"+It.host!=u.protocol+\"//\"+u.host}catch(e){d.crossDomain=!0}}if(d.data&&d.processData&&\"string\"!=typeof d.data&&(d.data=b.param(d.data,d.traditional)),Ft(Pt,d,n,E),l)return E;for(f in(c=b.event&&d.global)&&0==b.active++&&b.event.trigger(\"ajaxStart\"),d.type=d.type.toUpperCase(),d.hasContent=!Ht.test(d.type),i=d.url.replace(jt,\"\"),d.hasContent?d.data&&d.processData&&0===(d.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&(d.data=d.data.replace(Dt,\"+\")):(p=d.url.slice(i.length),d.data&&(d.processData||\"string\"==typeof d.data)&&(i+=(Ct.test(i)?\"&\":\"?\")+d.data,delete d.data),!1===d.cache&&(i=i.replace(qt,\"$1\"),p=(Ct.test(i)?\"&\":\"?\")+\"_=\"+Tt.guid+++p),d.url=i+p),d.ifModified&&(b.lastModified[i]&&E.setRequestHeader(\"If-Modified-Since\",b.lastModified[i]),b.etag[i]&&E.setRequestHeader(\"If-None-Match\",b.etag[i])),(d.data&&d.hasContent&&!1!==d.contentType||n.contentType)&&E.setRequestHeader(\"Content-Type\",d.contentType),E.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(\"*\"!==d.dataTypes[0]?\", \"+Mt+\"; q=0.01\":\"\"):d.accepts[\"*\"]),d.headers)E.setRequestHeader(f,d.headers[f]);if(d.beforeSend&&(!1===d.beforeSend.call(h,E,d)||l))return E.abort();if(C=\"abort\",m.add(d.complete),E.done(d.success),E.fail(d.error),r=Ft(Rt,d,n,E)){if(E.readyState=1,c&&g.trigger(\"ajaxSend\",[E,d]),l)return E;d.async&&d.timeout>0&&(s=e.setTimeout((function(){E.abort(\"timeout\")}),d.timeout));try{l=!1,r.send(w,S)}catch(e){if(l)throw e;S(-1,e)}}else S(-1,\"No Transport\");function S(t,n,a,u){var f,p,v,w,T,C=n;l||(l=!0,s&&e.clearTimeout(s),r=void 0,o=u||\"\",E.readyState=t>0?4:0,f=t>=200&&t<300||304===t,a&&(w=function(e,t,n){for(var r,i,o,a,s=e.contents,u=e.dataTypes;\"*\"===u[0];)u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+\" \"+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(d,E,a)),!f&&b.inArray(\"script\",d.dataTypes)>-1&&(d.converters[\"text script\"]=function(){}),w=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(!(a=l[u+\" \"+o]||l[\"* \"+o]))for(i in l)if((s=i.split(\" \"))[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e.throws)t=a(t);else try{t=a(t)}catch(e){return{state:\"parsererror\",error:a?e:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}(d,w,E,f),f?(d.ifModified&&((T=E.getResponseHeader(\"Last-Modified\"))&&(b.lastModified[i]=T),(T=E.getResponseHeader(\"etag\"))&&(b.etag[i]=T)),204===t||\"HEAD\"===d.type?C=\"nocontent\":304===t?C=\"notmodified\":(C=w.state,p=w.data,f=!(v=w.error))):(v=C,!t&&C||(C=\"error\",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+\"\",f?y.resolveWith(h,[p,C,E]):y.rejectWith(h,[E,C,v]),E.statusCode(x),x=void 0,c&&g.trigger(f?\"ajaxSuccess\":\"ajaxError\",[E,d,f?p:v]),m.fireWith(h,[E,C]),c&&(g.trigger(\"ajaxComplete\",[E,d]),--b.active||b.event.trigger(\"ajaxStop\")))}return E},getJSON:function(e,t,n){return b.get(e,t,n,\"json\")},getScript:function(e,t){return b.get(e,void 0,t,\"script\")}}),b.each([\"get\",\"post\"],(function(e,t){b[t]=function(e,n,r,i){return h(n)&&(i=i||r,r=n,n=void 0),b.ajax(b.extend({url:e,type:t,dataType:i,data:n,success:r},b.isPlainObject(e)&&e))}})),b.ajaxPrefilter((function(e){var t;for(t in e.headers)\"content-type\"===t.toLowerCase()&&(e.contentType=e.headers[t]||\"\")})),b._evalUrl=function(e,t,n){return b.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,converters:{\"text script\":function(){}},dataFilter:function(e){b.globalEval(e,t,n)}})},b.fn.extend({wrapAll:function(e){var t;return this[0]&&(h(e)&&(e=e.call(this[0])),t=b(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map((function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e})).append(this)),this},wrapInner:function(e){return h(e)?this.each((function(t){b(this).wrapInner(e.call(this,t))})):this.each((function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)}))},wrap:function(e){var t=h(e);return this.each((function(n){b(this).wrapAll(t?e.call(this,n):e)}))},unwrap:function(e){return this.parent(e).not(\"body\").each((function(){b(this).replaceWith(this.childNodes)})),this}}),b.expr.pseudos.hidden=function(e){return!b.expr.pseudos.visible(e)},b.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},b.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var $t={0:200,1223:204},_t=b.ajaxSettings.xhr();d.cors=!!_t&&\"withCredentials\"in _t,d.ajax=_t=!!_t,b.ajaxTransport((function(t){var n,r;if(d.cors||_t&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];for(a in t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i[\"X-Requested-With\"]||(i[\"X-Requested-With\"]=\"XMLHttpRequest\"),i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,\"abort\"===e?s.abort():\"error\"===e?\"number\"!=typeof s.status?o(0,\"error\"):o(s.status,s.statusText):o($t[s.status]||s.status,s.statusText,\"text\"!==(s.responseType||\"text\")||\"string\"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n(\"error\"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout((function(){n&&r()}))},n=n(\"abort\");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}})),b.ajaxPrefilter((function(e){e.crossDomain&&(e.contents.script=!1)})),b.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter(\"script\",(function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\")})),b.ajaxTransport(\"script\",(function(e){var t,n;if(e.crossDomain||e.scriptAttrs)return{send:function(r,i){t=b(\""
],
"text/plain": [
":Overlay\n",
" .Tiles.I :Tiles [x,y]\n",
" .Points.I :Points [Longitude,Latitude] (name)"
]
},
"execution_count": 5,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1003"
}
},
"output_type": "execute_result"
}
],
"source": [
"data.hvplot(geo=True, tiles=\"OSM\", alpha=0.5, width=600, height=600, hover_cols=[\"name\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Baseline (nonspatial) regression\n",
"\n",
"Before introducing explicitly spatial methods, we will run a simple linear regression model. This will allow us, on the one hand, set the main principles of hedonic modeling and how to interpret the coefficients, which is good because the spatial models will build on this; and, on the other hand, it will provide a baseline model that we can use to evaluate how meaningful the spatial extensions are.\n",
"\n",
"Essentially, the core of a linear regression is to explain a given variable -the price of a listing $i$ on AirBnb ($P_i$)- as a linear function of a set of other characteristics we will collectively call $X_i$:\n",
"\n",
"$$\n",
"\\ln(P_i) = \\alpha + \\beta X_i + \\epsilon_i\n",
"$$\n",
"\n",
"For several reasons, it is common practice to introduce the price in logarithms, so we will do so here. Additionally, since this is a probabilistic model, we add an error term $\\epsilon_i$ that is assumed to be well-behaved (i.i.d. as a normal).\n",
"\n",
"For our example, we will consider the following set of explanatory features of each listed property:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"explanatory_vars = ['host_listings_count', 'bathrooms', 'bedrooms', 'beds', 'guests_included']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Additionally, we are going to derive a new feature of a listing from the amenities variable. Let us construct a variable that takes 1 if the listed property has a pool and 0 otherwise:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def has_pool(a):\n",
" if 'Pool' in a:\n",
" return 1\n",
" else:\n",
" return 0\n",
" \n",
"data['pool'] = data['amenities'].apply(has_pool)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's calculate the logarithmic value from the price. Let's first check our values:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 $300.00\n",
"1 $99.00\n",
"2 $599.00\n",
"3 $100.00\n",
"4 $54.00\n",
"Name: price, dtype: object"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data[\"price\"].head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we can see, our values are represented as strings with a dollar sign. Before we can take a logarithmic value out of them, we need to remove the dollar sign and convert the values to floats:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Remove dollar sign and the thousand separator (comma, e.g. 1000,000.00) and convert to float\n",
"data[\"price\"] = data[\"price\"].str.replace(\"$\", '', regex=True).str.replace(\",\", \"\").astype(float)\n",
"data[\"log_price\"] = np.log(data[\"price\"] + 0.000001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Do we have any missing values in our dependent or explanatory variables?"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Has missing values: True\n"
]
}
],
"source": [
"all_model_attributes = [\"price\"] + explanatory_vars\n",
"has_nans = False\n",
"for attr in all_model_attributes:\n",
" if data[attr].hasnans:\n",
" has_nans = True\n",
"print(\"Has missing values:\", has_nans)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, as we can see there are missing values, hence, let's remove them before continuing:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"data = data.dropna(subset=all_model_attributes).copy()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To run the model, we can use the `spreg` module in `PySAL`, which implements a standard OLS routine, but is particularly well suited for regressions on spatial data. Also, although for the initial model we do not need it, let us build a spatial weights matrix that connects every observation to its 8 nearest neighbors. This will allow us to get extra diagnostics from the baseline model."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/hentenka/miniconda3/envs/sustainability/lib/python3.8/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected: \n",
" There are 6 disconnected components.\n",
" warnings.warn(message)\n"
]
},
{
"data": {
"text/plain": [
""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"w = weights.KNN.from_dataframe(data, k=8)\n",
"w.transform = 'R'\n",
"w"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At this point, we are ready to fit the regression:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"m1 = spreg.OLS(data[['log_price']].values, data[explanatory_vars].values, \n",
" name_y = 'log_price', name_x = explanatory_vars)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get a quick glimpse of the results, we can print its summary:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"REGRESSION\n",
"----------\n",
"SUMMARY OF OUTPUT: ORDINARY LEAST SQUARES\n",
"-----------------------------------------\n",
"Data set : unknown\n",
"Weights matrix : None\n",
"Dependent Variable : log_price Number of Observations: 9405\n",
"Mean dependent var : 5.2091 Number of Variables : 6\n",
"S.D. dependent var : 0.9274 Degrees of Freedom : 9399\n",
"R-squared : 0.4135\n",
"Adjusted R-squared : 0.4132\n",
"Sum squared residual: 4743.292 F-statistic : 1325.2928\n",
"Sigma-square : 0.505 Prob(F-statistic) : 0\n",
"S.E. of regression : 0.710 Log likelihood : -10126.208\n",
"Sigma-square ML : 0.504 Akaike info criterion : 20264.416\n",
"S.E of regression ML: 0.7102 Schwarz criterion : 20307.310\n",
"\n",
"------------------------------------------------------------------------------------\n",
" Variable Coefficient Std.Error t-Statistic Probability\n",
"------------------------------------------------------------------------------------\n",
" CONSTANT 4.1513682 0.0163707 253.5854585 0.0000000\n",
" host_listings_count -0.0000414 0.0001331 -0.3109881 0.7558165\n",
" bathrooms 0.2958058 0.0148994 19.8534819 0.0000000\n",
" bedrooms 0.3303400 0.0124747 26.4807231 0.0000000\n",
" beds 0.0203732 0.0075692 2.6915817 0.0071240\n",
" guests_included 0.0035146 0.0046767 0.7515178 0.4523599\n",
"------------------------------------------------------------------------------------\n",
"\n",
"REGRESSION DIAGNOSTICS\n",
"MULTICOLLINEARITY CONDITION NUMBER 9.185\n",
"\n",
"TEST ON NORMALITY OF ERRORS\n",
"TEST DF VALUE PROB\n",
"Jarque-Bera 2 1026360.300 0.0000\n",
"\n",
"DIAGNOSTICS FOR HETEROSKEDASTICITY\n",
"RANDOM COEFFICIENTS\n",
"TEST DF VALUE PROB\n",
"Breusch-Pagan test 5 1163.889 0.0000\n",
"Koenker-Bassett test 5 43.892 0.0000\n",
"================================ END OF REPORT =====================================\n"
]
}
],
"source": [
"print(m1.summary)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Results are largely unsurprising, but nonetheless reassuring. Both an extra bedroom and an extra bathroom increase the final price around 30%. Accounting for those, an extra bed pushes the price about 2%. Neither the number of guests included nor the number of listings the host has in total have a significant effect on the final price.\n",
"\n",
"Including a spatial weights object in the regression buys you an extra bit: the summary provides results on the diagnostics for spatial dependence. These are a series of statistics that test whether the residuals of the regression are spatially correlated, against the null of a random distribution over space. If the latter is rejected a key assumption of OLS, independently distributed error terms, is violated. Depending on the structure of the spatial pattern, different strategies have been defined within the spatial econometrics literature to deal with them. The main summary from the diagnostics for spatial dependence is that there is clear evidence to reject the null of spatial randomness in the residuals, hence an explicitly spatial approach is warranted.\n",
"\n",
"## Spatially lagged exogenous regressors (`WX`)\n",
"\n",
"The first and most straightforward way to introduce space is by **\"spatially lagging\" one of the explanatory variables**. Mathematically, this can be expressed as follows:\n",
"\n",
"$$\n",
"\\ln(P_i) = \\alpha + \\beta X_i + \\delta \\sum_j w_{ij} X'_i + \\epsilon_i\n",
"$$\n",
"\n",
"where $\\ln(P_i)$ is our dependent variable (logarithmic price), $X'_i$ is a subset of $X_i$, although it could encompass all of the explanatory variables, and $w_{ij}$ is the $ij$-th cell of a spatial weights matrix $W$. Because $W$ assigns non-zero values only to spatial neighbors, if $W$ is row-standardized (customary in this context), then $\\sum_j w_{ij} X'_i$ captures the average value of $X'_i$ in the surroundings of location $i$. This is what we call the *spatial lag* of $X_i$. Also, since it is a spatial transformation of an explanatory variable, the standard estimation approach -OLS- is sufficient: spatially lagging the variables does not violate any of the assumptions on which OLS relies.\n",
"\n",
"Usually, we will want to spatially lag variables that we think may affect the price of a house in a given location. For example, one could think that pools represent a visual amenity. If that is the case, then listed properties surrounded by other properties with pools might, everything else equal, be more expensive. To calculate the number of pools surrounding each property, we can build an alternative weights matrix that we do not row-standardize:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" id | \n",
" listing_url | \n",
" scrape_id | \n",
" last_scraped | \n",
" name | \n",
" summary | \n",
" space | \n",
" description | \n",
" experiences_offered | \n",
" neighborhood_overview | \n",
" ... | \n",
" cancellation_policy | \n",
" require_guest_profile_picture | \n",
" require_guest_phone_verification | \n",
" calculated_host_listings_count | \n",
" reviews_per_month | \n",
" geometry | \n",
" index_right | \n",
" pool | \n",
" log_price | \n",
" w_pool | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 72635 | \n",
" https://www.airbnb.com/rooms/72635 | \n",
" 20151107173015 | \n",
" 2015-11-08 | \n",
" 3 Private Bedrooms, SW Austin | \n",
" Conveniently located 10-15 from downtown in SW... | \n",
" We have three spare bedrooms, each with a quee... | \n",
" Conveniently located 10-15 from downtown in SW... | \n",
" none | \n",
" Location and convenience are key. Easy access... | \n",
" ... | \n",
" moderate | \n",
" f | \n",
" f | \n",
" 1 | \n",
" 0.02 | \n",
" POINT (-97.88431 30.20282) | \n",
" 14 | \n",
" 0 | \n",
" 5.703782 | \n",
" 2.0 | \n",
"
\n",
" \n",
" | 1 | \n",
" 5386323 | \n",
" https://www.airbnb.com/rooms/5386323 | \n",
" 20151107173015 | \n",
" 2015-11-07 | \n",
" Cricket Trailer | \n",
" Rent this cool concept trailer that has everyt... | \n",
" Rental arrangements for this trailer allows yo... | \n",
" Rent this cool concept trailer that has everyt... | \n",
" none | \n",
" We're talking about wherever you'd like in the... | \n",
" ... | \n",
" moderate | \n",
" f | \n",
" f | \n",
" 1 | \n",
" NaN | \n",
" POINT (-97.90068 30.19941) | \n",
" 14 | \n",
" 0 | \n",
" 4.595120 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | 2 | \n",
" 8536913 | \n",
" https://www.airbnb.com/rooms/8536913 | \n",
" 20151107173015 | \n",
" 2015-11-08 | \n",
" Brand-New 3BR Austin Home | \n",
" Brand-new 3BR/2BA Austin home with landscaped ... | \n",
" Feel instantly at home at our brand new 3BR/2B... | \n",
" Brand-new 3BR/2BA Austin home with landscaped ... | \n",
" none | \n",
" Entertainment and activities are plentiful her... | \n",
" ... | \n",
" strict | \n",
" f | \n",
" f | \n",
" 2 | \n",
" NaN | \n",
" POINT (-97.88832 30.16943) | \n",
" 14 | \n",
" 0 | \n",
" 6.395262 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | 3 | \n",
" 8542056 | \n",
" https://www.airbnb.com/rooms/8542056 | \n",
" 20151107173015 | \n",
" 2015-11-07 | \n",
" Private room & Bathroom. | \n",
" 15 minutes from Downtown & Zilker Park. Use of... | \n",
" NaN | \n",
" 15 minutes from Downtown & Zilker Park. Use of... | \n",
" none | \n",
" NaN | \n",
" ... | \n",
" flexible | \n",
" f | \n",
" f | \n",
" 1 | \n",
" NaN | \n",
" POINT (-97.90744 30.18676) | \n",
" 14 | \n",
" 0 | \n",
" 4.605170 | \n",
" 0.0 | \n",
"
\n",
" \n",
" | 4 | \n",
" 6385948 | \n",
" https://www.airbnb.com/rooms/6385948 | \n",
" 20151107173015 | \n",
" 2015-11-08 | \n",
" S. Austin, convenient to MoPac | \n",
" Private upstairs room with bath in far South A... | \n",
" In addition to the first bedroom, we have an a... | \n",
" Private upstairs room with bath in far South A... | \n",
" none | \n",
" Quiet, residential neighborhood that feels a l... | \n",
" ... | \n",
" flexible | \n",
" f | \n",
" f | \n",
" 1 | \n",
" NaN | \n",
" POINT (-97.92022 30.18770) | \n",
" 14 | \n",
" 0 | \n",
" 3.988984 | \n",
" 1.0 | \n",
"
\n",
" \n",
"
\n",
"
5 rows × 97 columns
\n",
"
"
],
"text/plain": [
" id listing_url scrape_id last_scraped \\\n",
"0 72635 https://www.airbnb.com/rooms/72635 20151107173015 2015-11-08 \n",
"1 5386323 https://www.airbnb.com/rooms/5386323 20151107173015 2015-11-07 \n",
"2 8536913 https://www.airbnb.com/rooms/8536913 20151107173015 2015-11-08 \n",
"3 8542056 https://www.airbnb.com/rooms/8542056 20151107173015 2015-11-07 \n",
"4 6385948 https://www.airbnb.com/rooms/6385948 20151107173015 2015-11-08 \n",
"\n",
" name \\\n",
"0 3 Private Bedrooms, SW Austin \n",
"1 Cricket Trailer \n",
"2 Brand-New 3BR Austin Home \n",
"3 Private room & Bathroom. \n",
"4 S. Austin, convenient to MoPac \n",
"\n",
" summary \\\n",
"0 Conveniently located 10-15 from downtown in SW... \n",
"1 Rent this cool concept trailer that has everyt... \n",
"2 Brand-new 3BR/2BA Austin home with landscaped ... \n",
"3 15 minutes from Downtown & Zilker Park. Use of... \n",
"4 Private upstairs room with bath in far South A... \n",
"\n",
" space \\\n",
"0 We have three spare bedrooms, each with a quee... \n",
"1 Rental arrangements for this trailer allows yo... \n",
"2 Feel instantly at home at our brand new 3BR/2B... \n",
"3 NaN \n",
"4 In addition to the first bedroom, we have an a... \n",
"\n",
" description experiences_offered \\\n",
"0 Conveniently located 10-15 from downtown in SW... none \n",
"1 Rent this cool concept trailer that has everyt... none \n",
"2 Brand-new 3BR/2BA Austin home with landscaped ... none \n",
"3 15 minutes from Downtown & Zilker Park. Use of... none \n",
"4 Private upstairs room with bath in far South A... none \n",
"\n",
" neighborhood_overview ... cancellation_policy \\\n",
"0 Location and convenience are key. Easy access... ... moderate \n",
"1 We're talking about wherever you'd like in the... ... moderate \n",
"2 Entertainment and activities are plentiful her... ... strict \n",
"3 NaN ... flexible \n",
"4 Quiet, residential neighborhood that feels a l... ... flexible \n",
"\n",
" require_guest_profile_picture require_guest_phone_verification \\\n",
"0 f f \n",
"1 f f \n",
"2 f f \n",
"3 f f \n",
"4 f f \n",
"\n",
" calculated_host_listings_count reviews_per_month \\\n",
"0 1 0.02 \n",
"1 1 NaN \n",
"2 2 NaN \n",
"3 1 NaN \n",
"4 1 NaN \n",
"\n",
" geometry index_right pool log_price w_pool \n",
"0 POINT (-97.88431 30.20282) 14 0 5.703782 2.0 \n",
"1 POINT (-97.90068 30.19941) 14 0 4.595120 0.0 \n",
"2 POINT (-97.88832 30.16943) 14 0 6.395262 0.0 \n",
"3 POINT (-97.90744 30.18676) 14 0 4.605170 0.0 \n",
"4 POINT (-97.92022 30.18770) 14 0 3.988984 1.0 \n",
"\n",
"[5 rows x 97 columns]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create weigts\n",
"w_pool = weights.KNN.from_dataframe(data, k=8)\n",
"# Assign spatial lag based on the pool values\n",
"lagged = data.assign(w_pool=weights.spatial_lag.lag_spatial(w_pool, data['pool'].values))\n",
"lagged.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now we can run the model, which has the same setup as `m1`, with the exception that it includes the number of AirBnb properties with pools surrounding each house:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"# Add pool to the explanatory variables\n",
"extended_vars = explanatory_vars + [\"pool\", \"w_pool\"]\n",
"\n",
"m2 = spreg.OLS(lagged[['log_price']].values, lagged[extended_vars].values, \n",
" name_y = 'log_price', name_x = extended_vars)\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"REGRESSION\n",
"----------\n",
"SUMMARY OF OUTPUT: ORDINARY LEAST SQUARES\n",
"-----------------------------------------\n",
"Data set : unknown\n",
"Weights matrix : None\n",
"Dependent Variable : log_price Number of Observations: 9405\n",
"Mean dependent var : 5.2091 Number of Variables : 8\n",
"S.D. dependent var : 0.9274 Degrees of Freedom : 9397\n",
"R-squared : 0.4160\n",
"Adjusted R-squared : 0.4156\n",
"Sum squared residual: 4722.719 F-statistic : 956.4067\n",
"Sigma-square : 0.503 Prob(F-statistic) : 0\n",
"S.E. of regression : 0.709 Log likelihood : -10105.768\n",
"Sigma-square ML : 0.502 Akaike info criterion : 20227.536\n",
"S.E of regression ML: 0.7086 Schwarz criterion : 20284.728\n",
"\n",
"------------------------------------------------------------------------------------\n",
" Variable Coefficient Std.Error t-Statistic Probability\n",
"------------------------------------------------------------------------------------\n",
" CONSTANT 4.1070923 0.0178568 230.0016122 0.0000000\n",
" host_listings_count -0.0000198 0.0001329 -0.1492746 0.8813402\n",
" bathrooms 0.2874081 0.0149634 19.2074072 0.0000000\n",
" bedrooms 0.3370220 0.0124981 26.9659179 0.0000000\n",
" beds 0.0218039 0.0075575 2.8850591 0.0039223\n",
" guests_included 0.0048721 0.0046719 1.0428516 0.2970439\n",
" pool 0.0415857 0.0217379 1.9130499 0.0557720\n",
" w_pool 0.0132716 0.0037939 3.4981477 0.0004707\n",
"------------------------------------------------------------------------------------\n",
"\n",
"REGRESSION DIAGNOSTICS\n",
"MULTICOLLINEARITY CONDITION NUMBER 9.894\n",
"\n",
"TEST ON NORMALITY OF ERRORS\n",
"TEST DF VALUE PROB\n",
"Jarque-Bera 2 1092974.908 0.0000\n",
"\n",
"DIAGNOSTICS FOR HETEROSKEDASTICITY\n",
"RANDOM COEFFICIENTS\n",
"TEST DF VALUE PROB\n",
"Breusch-Pagan test 7 1809.139 0.0000\n",
"Koenker-Bassett test 7 66.192 0.0000\n",
"================================ END OF REPORT =====================================\n"
]
}
],
"source": [
"print(m2.summary)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Results are largely consistent with the original model. Also, incidentally, the number of pools surrounding a property does not appear to have any significant effect on the price of a given property. This could be for a host of reasons: maybe AirBnb customers do not value the number of pools surrounding a property where they are looking to stay; but maybe they do but our dataset only allows us to capture the number of pools in *other* AirBnb properties, which is not necessarily a good proxy of the number of pools in the immediate surroundings of a given property.\n",
"\n",
"## Spatially lagged endogenous regressors (`WY`)\n",
"\n",
"In a similar way to how we have included the spatial lag, one could think the prices of houses surrounding a given property also enter its own price function. In math terms, this implies the following:\n",
"\n",
"$$\n",
"\\ln(P_i) = \\alpha + \\lambda \\sum_j w_{ij} \\ln(P_i) + \\beta X_i + \\epsilon_i\n",
"$$\n",
"\n",
"This is essentially what we call a *spatial lag* model in spatial econometrics. Two calls for caution:\n",
"\n",
"1. Unlike before, this specification *does* violate some of the assumptions on which OLS relies. In particular, it is including an endogenous variable $\\ln(P_i)$ on the right-hand side. This means we need a new estimation method to obtain reliable coefficients. The technical details of this go well beyond the scope of this tutorial. But we can offload those to `PySAL` and use the `GM_Lag` class, which implements the state-of-the-art approach to estimate this model.\n",
"1. A more conceptual *gotcha*: you might be tempted to read the equation above as the effect of the price in neighboring locations $j$ on that of location $i$. This is not exactly the exact interpretation. Instead, we need to realize this is all assumed to be a \"joint decission\": rather than some houses setting their price first and that having a subsequent effect on others, what the equation models is an interdependent process by which each owner sets her own price *taking into account* the price that will be set in neighboring locations. This might read a bit like a technical subtlety and, to some extent, it is; but it is important to keep it in mind when you are interpreting the results.\n",
"\n",
"Let us see how you would run this using `PySAL`:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"variables = explanatory_vars + [\"pool\"]\n",
"m3 = spreg.GM_Lag(data[['log_price']].values, data[variables].values, \n",
" w=w,\n",
" name_y = 'ln(price)', name_x = variables)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"REGRESSION\n",
"----------\n",
"SUMMARY OF OUTPUT: SPATIAL TWO STAGE LEAST SQUARES\n",
"--------------------------------------------------\n",
"Data set : unknown\n",
"Weights matrix : unknown\n",
"Dependent Variable : ln(price) Number of Observations: 9405\n",
"Mean dependent var : 5.2091 Number of Variables : 8\n",
"S.D. dependent var : 0.9274 Degrees of Freedom : 9397\n",
"Pseudo R-squared : 0.4528\n",
"Spatial Pseudo R-squared: 0.4164\n",
"\n",
"------------------------------------------------------------------------------------\n",
" Variable Coefficient Std.Error z-Statistic Probability\n",
"------------------------------------------------------------------------------------\n",
" CONSTANT 3.5328351 0.1106839 31.9182262 0.0000000\n",
" host_listings_count -0.0000774 0.0001290 -0.6001854 0.5483827\n",
" bathrooms 0.2727659 0.0147162 18.5351227 0.0000000\n",
" bedrooms 0.3315183 0.0121262 27.3390332 0.0000000\n",
" beds 0.0200516 0.0073224 2.7383980 0.0061739\n",
" guests_included 0.0032809 0.0045258 0.7249351 0.4684918\n",
" pool 0.0890127 0.0162495 5.4778874 0.0000000\n",
" W_ln(price) 0.1209172 0.0223031 5.4215449 0.0000001\n",
"------------------------------------------------------------------------------------\n",
"Instrumented: W_ln(price)\n",
"Instruments: W_bathrooms, W_bedrooms, W_beds, W_guests_included,\n",
" W_host_listings_count, W_pool\n",
"================================ END OF REPORT =====================================\n"
]
}
],
"source": [
"print(m3.summary)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we can see, results are again very similar in all the other variable. It is also very clear that the estimate of the spatial lag of price is statistically significant. This points to evidence that there are processes of spatial interaction between property owners when they set their price.\n",
"\n",
"## Prediction performance of spatial models\n",
"\n",
"Even if we are not interested in the interpretation of the model to learn more about how alternative factors determine the price of an AirBnb property, spatial econometrics can be useful. In a purely predictive setting, the use of explicitly spatial models is likely to improve accuracy in cases where space plays a key role in the data generating process. To have a quick look at this issue, we can use the mean squared error (MSE), a standard metric of accuracy in the machine learning literature, to evaluate whether explicitly spatial models are better than traditional, non-spatial ones:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Lag 0.501873\n",
"OLS+W 0.502150\n",
"OLS 0.504337\n",
"dtype: float64"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.metrics import mean_squared_error as mse\n",
"\n",
"mses = pd.Series({'OLS': mse(data[\"log_price\"], m1.predy.flatten()), \\\n",
" 'OLS+W': mse(data[\"log_price\"], m2.predy.flatten()), \\\n",
" 'Lag': mse(data[\"log_price\"], m3.predy_e)\n",
" })\n",
"mses.sort_values()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that the inclusion of the number of surrounding pools slightly reduces the MSE, and the inclusion of the spatial lag of price improves the accuracy of the model even further."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
},
"pycharm": {
"stem_cell": {
"cell_type": "raw",
"metadata": {
"collapsed": false
},
"source": []
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}