Compare commits
8 Commits
c3c309ab60
...
a2a13d1b98
Author | SHA1 | Date |
---|---|---|
Craig Oates | a2a13d1b98 | 2 months ago |
Craig Oates | d13ef2e65c | 2 months ago |
Craig Oates | b0fbd94f6e | 2 months ago |
Craig Oates | 17a7a802d2 | 2 months ago |
Craig Oates | e7aa426b23 | 2 months ago |
Craig Oates | 66c055a473 | 2 months ago |
Craig Oates | 5e2640a21d | 2 months ago |
Craig Oates | 5facabddf8 | 2 months ago |
10 changed files with 294 additions and 19 deletions
@ -0,0 +1,10 @@
|
||||
<html><head><style>html{ |
||||
height: 100%; |
||||
} |
||||
|
||||
html body{ |
||||
height: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
}</style><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega@5'></script><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega-lite@5'></script><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega-embed@6'></script></head><body><div id='vis'></div><script>var spec = {"data":{"values":[{"rowId":11,"rent":1089,"location":"Cross Street Manchester M2","url":"https://www.zoopla.co.uk/to-rent/details/66673111/","description":"Listing code 692841. Our contemporary studio apartments at 25 Cross Street are thoughtfully designed to a high standard.Featuring a comfy double ..."},{"rowId":8,"rent":1050,"location":"Little Lever Street Manchester Greater Manchester M1","url":"https://www.zoopla.co.uk/to-rent/details/65042494/","description":"** available from 19/04/2024 ** ** all bills inclusive in rent ** Reeds Rains are delighted to market this fantastic furnished studio apartment ..."},{"rowId":5,"rent":1250,"location":"Arches Whitworth Street West Manchester M1","url":"https://www.zoopla.co.uk/to-rent/details/66338812/","description":"*3 month agreements only - available 23rd March* A true Manchester gem minutes from the Northern Quarter Canal Street and Piccadilly. This is ..."},{"rowId":3,"rent":1150,"location":"Water Street Manchester M3","url":"https://www.zoopla.co.uk/to-rent/details/66713818/","description":"1-6 months Tenancy bills included no couples due to regulations**Perfect for Contractors & Work Teams****Perfect for Business ..."},{"rowId":2,"rent":1150,"location":"Arches Whitworth Street West Manchester M1","url":"https://www.zoopla.co.uk/to-rent/details/65630906/","description":"**3 month agreements only - available 23rd March** A true Manchester gem minutes from the Northern Quarter Canal Street and Piccadilly. This is ..."}]},"$schema":"https://vega.github.io/schema/vega-lite/v5.json","title":"Rent Rates for Manchester on Zoople (18/03/2024)","width":600,"height":600,"layer":[{"mark":{"type":"bar"},"encoding":{"x":{"field":"rowId","title":"Assigned Id.","type":"nominal","axis":{"labelAngle":0}},"y":{"field":"rent","title":"Monthly Rent with Bills Inc. (£)","type":"quantitative"},"tooltip":{"field":"rent"}}},{"mark":{"type":"rule","color":"darkorange","size":3},"encoding":{"y":{"field":"rent","type":"quantitative","aggregate":"average"},"tooltip":{"field":"rent","type":"quantitative","aggregate":"average"}}}]}; vegaEmbed("#vis", spec).then(result => console.log(result)).catch(console.warn);</script></body></html> |
After Width: | Height: | Size: 38 KiB |
@ -1,10 +0,0 @@
|
||||
<html><head><style>html{ |
||||
height: 100%; |
||||
} |
||||
|
||||
html body{ |
||||
height: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
}</style><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega@5'></script><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega-lite@5'></script><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega-embed@6'></script></head><body><div id='vis'></div><script>var spec = {"data":{"values":[{"xAxis":"Open Rent","yAxis":735},{"xAxis":"On The Market","yAxis":1005},{"xAxis":"Roomies","yAxis":641},{"xAxis":"Ideal Flatmate","yAxis":714},{"xAxis":"Spare Room","yAxis":589},{"xAxis":"Right Move","yAxis":1204}]},"$schema":"https://vega.github.io/schema/vega-lite/v5.json","title":"Monthly Average Rent Rates (Bills Inc.) Manchester Feb. 2024","mark":"bar","width":600,"height":600,"layer":[{"mark":{"type":"bar"},"encoding":{"x":{"field":"xAxis","title":"Company","type":"nominal","axis":{"labelAngle":0}},"y":{"field":"yAxis","title":"Rent (£)","type":"quantitative"},"tooltip":{"field":"yAxis"}}},{"mark":{"type":"rule","color":"darkorange","size":3},"encoding":{"y":{"field":"yAxis","type":"quantitative","aggregate":"average"},"tooltip":{"field":"yAxis","type":"quantitative","aggregate":"average"}}}]}; vegaEmbed("#vis", spec).then(result => console.log(result)).catch(console.warn);</script></body></html> |
Before Width: | Height: | Size: 39 KiB |
@ -0,0 +1,10 @@
|
||||
<html><head><style>html{ |
||||
height: 100%; |
||||
} |
||||
|
||||
html body{ |
||||
height: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
}</style><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega@5'></script><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega-lite@5'></script><script type='text/javascript' src='https://cdn.jsdelivr.net/npm/vega-embed@6'></script></head><body><div id='vis'></div><script>var spec = {"data":{"values":[{"xAxis":"Zoopla","yAxis":1138},{"xAxis":"Open Rent","yAxis":735},{"xAxis":"On The Market","yAxis":1005},{"xAxis":"Roomies","yAxis":641},{"xAxis":"Ideal Flatmate","yAxis":714},{"xAxis":"Spare Room","yAxis":589},{"xAxis":"Right Move","yAxis":1204}]},"$schema":"https://vega.github.io/schema/vega-lite/v5.json","title":"Monthly Average Rent Rates (Bills Inc.) Manchester Feb–March 2024","mark":"bar","width":600,"height":600,"layer":[{"mark":{"type":"bar"},"encoding":{"x":{"field":"xAxis","title":"Company","type":"nominal","axis":{"labelAngle":0}},"y":{"field":"yAxis","title":"Rent (£)","type":"quantitative"},"tooltip":{"field":"yAxis"}}},{"mark":{"type":"rule","color":"darkorange","size":3},"encoding":{"y":{"field":"yAxis","type":"quantitative","aggregate":"average"},"tooltip":{"field":"yAxis","type":"quantitative","aggregate":"average"}}}]}; vegaEmbed("#vis", spec).then(result => console.log(result)).catch(console.warn);</script></body></html> |
After Width: | Height: | Size: 40 KiB |
|
|
@ -0,0 +1,257 @@
|
||||
#+options: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline author:t |
||||
#+options: broken-links:nil c:nil creator:nil d:(not "LOGBOOK") date:t e:t |
||||
#+options: email:nil expand-links:t f:t inline:t num:t p:nil pri:nil prop:nil |
||||
#+options: stat:t tags:t tasks:t tex:t timestamp:t title:t toc:t todo:t |:t |
||||
#+title: Zoopla Manchester |
||||
#+date: \today |
||||
#+author: Craig Oates |
||||
#+email: craig@craigoates.net |
||||
#+language: en |
||||
#+select_tags: export |
||||
#+exclude_tags: noexport |
||||
#+creator: Emacs 29.1.90 (Org mode 9.7-pre) |
||||
#+cite_export: |
||||
|
||||
* Setup Common Lisp Environment |
||||
|
||||
I’ve copied the following code block over from other files. Run it if this is |
||||
your first file open in the session. |
||||
|
||||
#+begin_src lisp :session :results silent |
||||
(ql:quickload :com.inuoe.jzon) ; JSON parser. |
||||
(ql:quickload :dexador) ; HTTP requests. |
||||
(ql:quickload :plump) ; HTML/XML parser. |
||||
(ql:quickload :lquery) ; HTML/DOM manipulation. |
||||
(ql:quickload :lparallel) ; Parallel programming. |
||||
(ql:quickload :cl-ppcre) ; RegEx. library. |
||||
(ql:quickload :plot/vega) ; Vega plotting library. |
||||
(ql:quickload :lisp-stat) ; Stat's library. |
||||
(ql:quickload :data-frame) ; Data frame library eqv. to Python's Numpy. |
||||
(ql:quickload :str) ; String library, expands on 'string' library. |
||||
#+end_src |
||||
|
||||
* Gather Zoopla Rent Data (Manually) |
||||
|
||||
- [[https://www.zoopla.co.uk/][Zoopla]] |
||||
|
||||
The site produced a single page so I didn't feel the need to scrap the data. I |
||||
just saved the page into =raw-data/external/2024-03-18-zoopla-rent-manc/=. The |
||||
data is the actual HTML and CSS, so the files will not be committed to the |
||||
repository, to match the established behaviour of the other sites I've already |
||||
looked at. |
||||
|
||||
The filters I used: |
||||
|
||||
- Date: 2024-03-18 |
||||
- Location: Manchester City Centre, Greater Manchester |
||||
- Radius: 'This area only' |
||||
- Price Range: £400–£1,300 pcm |
||||
- Only monthly rents listed |
||||
|
||||
* Clean Up and Parse Data |
||||
|
||||
Going to separate the listings out into their own files, to match the |
||||
established behaviour with other sites I've looked at. |
||||
|
||||
#+begin_src shell :results silent |
||||
mkdir raw-data/external/2024-03-18-zoopla-rent-manc-listings/ |
||||
#+end_src |
||||
|
||||
[[file:./raw-data/external/2024-03-18-zoopla-rent-manc-listings/]] |
||||
|
||||
#+begin_src lisp :results silent |
||||
(let ((counter 0)) |
||||
(loop for file-path |
||||
in (directory #P"raw-data/external/2024-03-18-zoopla-rent-manc/*.html") |
||||
do (with-open-file (in-stream file-path) |
||||
(let* ((doc (plump:parse in-stream)) |
||||
;; .listing-info |
||||
(listings (lquery:$ doc ".dkr2t82" (serialize)))) |
||||
(loop for item across listings |
||||
do (let ((out-path |
||||
(merge-pathnames |
||||
#P"raw-data/external/2024-03-18-zoopla-rent-manc-listings/" |
||||
(format nil "listing-~a.html" (write-to-string counter))))) |
||||
(with-open-file (out-stream |
||||
out-path |
||||
:direction :output |
||||
:if-exists :supersede) |
||||
(format out-stream "~a~%" item)) |
||||
(incf counter))))))) |
||||
#+end_src |
||||
|
||||
#+begin_src shell :results output |
||||
COUNT=$(ls -1 "raw-data/external/2024-03-18-zoopla-rent-manc-listings/" | wc -l) |
||||
echo "There are $COUNT files in the directory." |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
: There are 14 files in the directory. |
||||
|
||||
There are some listings which are student-only. Unfortunately, there doesn't |
||||
seem to be a filter for removing student-only listings. So, I'll need to remove |
||||
them manually at little later down the line. The total amount of listing is |
||||
small enough for it to not be a problem. |
||||
|
||||
** Create CSV of Listings |
||||
|
||||
#+begin_src lisp :results output raw |
||||
(let ((row-id 0) |
||||
(out-file #P"working-data/2024-03-18-zoopla-manc.csv")) |
||||
(with-open-file (out-stream |
||||
out-file |
||||
:direction :output |
||||
:if-exists :supersede) |
||||
(format out-stream "ROW-ID,RENT,LOCATION,URL,DESCRIPTION~%") |
||||
(loop for input |
||||
in (directory #P"raw-data/external/2024-03-18-zoopla-rent-manc-listings/*.html") |
||||
do (with-open-file (in-stream input) |
||||
(let* ((doc (plump:parse in-stream)) |
||||
(price (lquery:$ doc "._64if862._194zg6t6" (text))) |
||||
(description (lquery:$ doc ".m6hnz63._194zg6t9" (text))) |
||||
;; e.g. Transform '£1,250 per month' to '1250'. |
||||
(cleaned-price |
||||
(first |
||||
(cl-ppcre:all-matches-as-strings |
||||
"\\d+" |
||||
(cl-ppcre:regex-replace-all |
||||
"[\\s\\n]+" |
||||
(format nil "~s" (str:replace-all "," "" (aref price 0))) |
||||
" ")))) |
||||
(location (lquery:$ doc "address" (text))) |
||||
(link (lquery:$ doc "a" (attr :href)))) |
||||
(format out-stream "~d,~d,~a,~a,~a~%" |
||||
row-id |
||||
cleaned-price |
||||
(str:replace-all "," " " (aref location 0)) |
||||
(cl-ppcre:regex-replace "\\?search.*" (aref link 0) "") |
||||
(str:replace-all "," " " (aref description 0))))) |
||||
(incf row-id))) |
||||
(format t "[[file:./~a]]" out-file)) |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
[[file:./working-data/2024-03-18-zoopla-manc.csv]] |
||||
|
||||
*I've manually removed the student-only listing, since creating the CSV file.* |
||||
File is left with 5 listings. |
||||
|
||||
* Explore CSV Data for Zoopla (2024-03-18) |
||||
|
||||
#+begin_src lisp :session |
||||
(lisp-stat:defdf *zoop-man* |
||||
(lisp-stat:read-csv #P"working-data/2024-03-18-zoopla-manc.csv")) |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
: #<DATA-FRAME:DATA-FRAME (5 observations of 5 variables)> |
||||
|
||||
The total amount of listings is tiny, so I can list them out here. |
||||
|
||||
#+begin_src lisp :session :results output drawer |
||||
(lisp-stat:print-markdown *zoop-man*) |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
:results: |
||||
| ROW-ID | RENT | LOCATION | URL | DESCRIPTION | |
||||
|--------+------+--------------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------| |
||||
| 2 | 1150 | Arches Whitworth Street West Manchester M1 | https://www.zoopla.co.uk/to-rent/details/65630906/ | **3 month agreements only - available 23rd March** A true Manchester gem minutes from the Northern Quarter Canal Street and Piccadilly. This is ... | |
||||
| 3 | 1150 | Water Street Manchester M3 | https://www.zoopla.co.uk/to-rent/details/66713818/ | 1-6 months Tenancy bills included no couples due to regulations**Perfect for Contractors & Work Teams****Perfect for Business ... | |
||||
| 5 | 1250 | Arches Whitworth Street West Manchester M1 | https://www.zoopla.co.uk/to-rent/details/66338812/ | *3 month agreements only - available 23rd March* A true Manchester gem minutes from the Northern Quarter Canal Street and Piccadilly. This is ... | |
||||
| 8 | 1050 | Little Lever Street Manchester Greater Manchester M1 | https://www.zoopla.co.uk/to-rent/details/65042494/ | ** available from 19/04/2024 ** ** all bills inclusive in rent ** Reeds Rains are delighted to market this fantastic furnished studio apartment ... | |
||||
| 11 | 1089 | Cross Street Manchester M2 | https://www.zoopla.co.uk/to-rent/details/66673111/ | Listing code 692841. Our contemporary studio apartments at 25 Cross Street are thoughtfully designed to a high standard.Featuring a comfy double ... | |
||||
:end: |
||||
|
||||
#+begin_src lisp :session :results file |
||||
(vega:defplot zoopla-monthly-manc |
||||
`(:title "Rent Rates for Manchester on Zoople (18/03/2024)" |
||||
:width 600 |
||||
:height 600 |
||||
:data ,*zoop-man* |
||||
:layer #((:mark (:type :bar) |
||||
:encoding (:x (:field :row-id :title "Assigned Id." :type :nominal :axis ("labelAngle" 0)) |
||||
:y (:field :rent :title "Monthly Rent with Bills Inc. (£)" :type :quantitative) |
||||
:tooltip (:field :rent))) |
||||
(:mark (:type rule :color "darkorange" :size 3) |
||||
:encoding (:y (:field :rent :type :quantitative :aggregate :average) |
||||
:tooltip (:field :rent :type :quantitative :aggregate :average)))))) |
||||
(vega:write-html zoopla-monthly-manc "renders/2024-03-18-zoopla-rent-manc.html") |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
[[file:renders/2024-03-18-zoopla-rent-manc.html]] |
||||
|
||||
#+begin_src shell :results silent |
||||
mv ~/Downloads/visualization.png ./renders/2024-03-18-zoopla-rent-manc.png |
||||
#+end_src |
||||
|
||||
[[file:./renders/2024-03-18-zoopla-rent-manc.png]] |
||||
|
||||
#+begin_src lisp :session :results output code raw |
||||
(format t "- Mean Rent: £ ~a~%" (float (lisp-stat:mean *zoop-man*:rent))) |
||||
(format t "- Min. Rent: £ ~d~%" (reduce #'min *zoop-man*:rent)) |
||||
(format t "- Max. Rent: £ ~d" (reduce #'max *zoop-man*:rent)) |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
- Mean Rent: £ 1137.8 |
||||
- Min. Rent: £ 1050 |
||||
- Max. Rent: £ 1250 |
||||
|
||||
#+begin_src calc :results output |
||||
1137.8 * 12 |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
: 13653.6 |
||||
|
||||
* Summary of Zoopla |
||||
|
||||
Based on the average rent for Zoopla, I would need to make around £14,000/yr to |
||||
cover my living costs. This doesn't include travel, food, clothing, socialising |
||||
or Income Tax Payments. |
||||
|
||||
Most listing were aimed at students and the number of listings was tiny, |
||||
especially when compared to [[file:./spare-room-manchester.org][Spareroom]] and [[file:./open-rent-manchester.org][Open Rent]]. |
||||
|
||||
To get an idea of what I need for ’survival mode’, I'll add £5,000 onto the |
||||
total above and apply the usual calculations, established in the other files. |
||||
|
||||
#+begin_src calc :results output |
||||
13653.6 + 5000 |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
: 18653.6 |
||||
|
||||
Using £18,653.6 as the starting point (see [[file:./uk-wage-tax.org][UK Wage and Tax Rated]], |
||||
|
||||
#+begin_src lisp :results output raw |
||||
(let* ((earning-target 18653.6) |
||||
(p-allow 12570) |
||||
(taxable-income (- earning-target p-allow)) |
||||
(tax-to-pay (* taxable-income 0.2)) |
||||
(total (- earning-target tax-to-pay))) |
||||
(format t "- Annual Target Salary: £~a~%" earning-target) |
||||
(format t "- Part of Salary which is Taxable: £~a~%" taxable-income) |
||||
(format t "- Tax to Pay: £~a~%" tax-to-pay) |
||||
(format t "- Salary After Tax: £~a~%" total)) |
||||
#+end_src |
||||
|
||||
#+RESULTS: |
||||
- Annual Target Salary: £18653.6 |
||||
- Part of Salary which is Taxable: £6083.5996 |
||||
- Tax to Pay: £1216.72 |
||||
- Salary After Tax: £17436.879 |
||||
|
||||
| Time Span | Value After Tax (£) | Mean Rent (£) | |
||||
|-----------------------+---------------------+---------------| |
||||
| Annually | 17436.88 | 1137.8 | |
||||
| Monthly (Before Rent) | 1453.0733 | | |
||||
| Monthly (After Rent) | 315.2733 | | |
||||
| Weekly (After Rent) | 78.818325 | | |
||||
| Daily (After Rent) | 11.259761 | | |
||||
#+TBLFM: @3$2=@-1/12::@4$2=@-1-@-2$+1::@5$2=@-1/4::@6$2=@-1/7 |
||||
|
||||
So, the spending limit is £11.26/day. |
Loading…
Reference in new issue