Building a recommendation engine inside Postgres with Python and Pandas (2020)
blog.crunchydata.com
blog.crunchydata.com
I think this is pretty common in the pandas world right
SQL is sometimes under appreciated as superior for grouping sorting and filtering... although with Bigquery and KSQL, SQL is definitely finding it's groove again.
Obviously in your case some trivial SQL would have sufficed, which I feel like should have been caught in an interview but could be excused for a junior eng.
Also Pandas is not an amazing choice for data engineering tasks in general IMO, type conversion wonkiness is one reason I have questions about people who decide to use Pandas for legitimate data engineering tasks (as opposed to exploratory work or analysis).
Using pandas but your data doesn’t fit in memory anymore? Here just use this fragile series of packages to distribute it across processors. Don’t reevaluate whether Pandas/Python is still the best choice, just layer more things in.
Run into issues with that approach? Here lift and shift your whole thing into Spark! Don’t ever optimise or actually engineer your process, just layer more things in!!!
Once you have done that, the logic will be easily translatable to SQL, and your brain is prepared for the SQL/relational-algebra way of thinking.
And good luck! You are doing it right!
You can keep using Panda code for exploratory work, then with a little effort move it to production with Spark runtime.
― Orson Scott Card, Ender's Game
I'm betting you are not an avid Pandas user ;)
The exploratory data analysis part is mostly a product of composability and verbosity. Composability is hard to define succinctly, but an easy example of it would just be the ability to easily define a filter as a variable and then reference that same filter in later code. Python provides a better interface for defining higher-order operations than pgPL/SQL, hands down. As for verbosity, I get data requests at work that require a lot of chained transformations - where I’d have to write 5-10 CTEs and a bunch of GROUP BYs and window functions that would total ~300 lines of SQL. Pandas equivalent would be <50 lines, and also easier to iterate on due to the composability factor. Other “killer-feature” examples of pandas terseness: https://pandas.pydata.org/pandas-docs/stable/reference/api/p..., https://pandas.pydata.org/pandas-docs/stable/reference/api/p....
Feature parity varies by db, but pandas is generally much more expressive and capable than SQL for string munging and time-series stuff.
This is before getting to Jupyter, which blows every SQL interface I’ve ever seen out of the water. One-liner plotting with Pandas is a complete game changer for investigating any unfamiliar dataset; the first class plotting integration is really hard to beat.
All that said, can’t comment on your coworker’s situation without knowing the context. A billion time series datapoints might be fine, but if it’s a wide table using 100s of gigs, probably not smart. I wouldn’t use pandas in a large ETL pipeline without a very good reason, nor would I ever use it for serious joining. If he is just straight up trying trying to functionally replace SQL with pandas code, he’s definitely not doing it right.
(Am data engineer, have been working professionally w/ SQL+Pandas on a near-daily basis for over 3 years.)
In general, if you are comparing to an SQL database, the most important is complex anaylsis/manipulation. Of course SQL is great for database level analysis - sorting/filtering/etc. But SQL queries for domain-specific analysis can become very opaque quickly and debugging of complex queries is a mess. Pandas is great for more complex manipulation as it keeps available the wider python ecosystem, allows for simpler debugging of complex processes through a REPL loop, links easily to visualisation, is pretty fast for some things through leveraging things like numpy, in-memory avoids multiple database calls, etc.
Obviously pandas isn't a great choice for persistent large datasets (maybe around the 0.1-1TB mark?) though, simply because it is memory stored.
The use cases definitely overlap significantly, but run into problems (typically ridiculous SQL queries on one side, giant data sets on the other) and you really need to stop and think about the tooling.
[0]https://pandas.pydata.org/docs/reference/api/pandas.read_sql...
I'm a scientist by profession and I've been working on building out several different generalized data processing pipelines for some specific problems in my sub-field, to make gathering and formatting in-situ data easier and more standardized/open/version-controlled. It's going great, worlds better than the smattering of matlab code strewn across the hard drives in the lab written in a non-collaborative manner and shared by email...
... but. I'll admit, I've run into a lot of footguns in the pandas API in terms of efficiency. You'll do something it what seems to be the logical way, or in a way that the API funnels you towards (like the groupby calls in the OP), and you'll quickly realize that if you're working on large-ish tables (>10Gb in memory) that it was the stupid way to do things. In terms of readable code to share with colleagues, pandas can't be beat, but things get wonky when you reach significant complexity and I would be surprised if it made any sense to use in a 'real' recommendation engine when considering developer productivity.
For your last paragraph, you're conflating the need to share code with the need to build a robust scalable service. Most research code are only needed for the paper and rarely touched again.
But doing a lot of these operations on-server makes sense when there's a significant volume of highly parallelizable transformations which need to be done on the data before it's usable.
Of course the best solution is likely to be a happy medium between the two, where simple low-level transformations are done on-server and the rest of the data preparation is done as the data is transferred to the client.
It was so hard to debug, so hard to safely maintain these procs, and a general nightmare
Plotting a Mandelbrot on the Mac would take a lot longer, even in C, than just making the printer do it.
Usually overnight, because the program took a couple hours to run most of the time.
OTOH, if you can pre-process the data (or shards) in the server (or servers), you won't need to move it across the network for processing.
Hard problems are hard and one of the reasons databases outlive their systems and developers is because moving that data is a Royal Pain.
Tightly coupling a lot of the application-specific compute in with how the day is stored and accessed says you up for even more difficulties when you need to debug, scale, migrate storage/compute or evolve your application faster or more radically than your data organisation.
However, pandas and python is here for what comes after that! Like a very complicated groupby logic, or invoking some apis to enhance data or complicated string processing or some kind of error measure or invoking some ML models or sending a slack message or building features for ranking or whatever.
I know a lot of people here love their SQL but queries like mentioned above are either impossible or become horrible horibly complicated and impossible to debug.
EDIT: And I want to add one extremely important thing. Whenever you can put stress away from your DB it is a good thing. Since your DB has to run all of the time and will be already stressed from Frontend requests. Combined with the fact that we are often talking about non-time sensitive work wouldn't it be better if your data scientists work on a database dump instead of continously hitting the DB?
And then ingest that read-replica to a column store data warehouse so that you don't have to think about reliability until someone starts yelling about speed or cost.
This makes sense in the context of the example the author copied from [0], where the dataset is sports equipment. Often purchased in bundles of related products for a specific sport.
Though it can be slow, harder to deal with memory usage issues, harder to debug in general, harder to extend/generalise.
And for me postgres is now one of multiple datastores so doing this is not as helpful.