Steves Data and R channel
Open in Telegram
375
Subscribers
No data24 hours
+17 days
-230 days
Posts Archive
Today is all about getting the max value in a row in #R
#RStats #Blog #Technology #Code #Programming #Scripting
Post: https://www.spsanderson.com/steveondata/posts/2025-09-22/
TL;DR: In today’s article, I talk about using Python and EZSheets to work with Google Sheets, sharing simple code and tips for beginners. 🐍📊
In today’s article, I discuss how to use Python, specifically the EZSheets library to automate tasks in Google Sheets. Since I’m learning as I write this series, there might be some mistakes, but I hope sharing my process helps other beginners too.
I start by explaining how to set up EZSheets and connect it to your Google account. You’ll see step-by-step instructions, like installing the library with
pip install ezsheets and getting your credentials ready. I also show how to open an existing spreadsheet or create a new one with code like:
import ezsheets
ss = ezsheets.createSpreadsheet('My New Sheet')
The article covers how to read and write data, update rows, and even use tables and bullet points to make things clearer. I include practical examples, such as adding sales data or tracking inventory, and explain each line of code in simple terms as best I can.
If you’re new to Python or Google Sheets automation, this article is meant to make things less confusing. I still find this a little confusing, getting the API from Google myself.
#GoogleSheetsPython #EZSheets #PythonForBeginners
Post: https://www.spsanderson.com/steveondata/posts/2025-09-17/library(RandomWalker)
library(dplyr)
library(ggplot2)
library(patchwork)
n <- 25
nw <- 3
x <- random_normal_walk(.num_walks = nw, .n = n, .samp = FALSE) |>
select(cum_sum_y)
y <- random_cauchy_walk(.num_walks = nw, .n = n, .samp = FALSE) |>
select(y)
xx <- predict(smooth.spline(x$cum_sum_y, spar = 0.005), seq(1, n, 0.01))$y[-1]
yy <- predict(smooth.spline(y$y, spar = 0.005), seq(1, n, 0.01))$y[-1]
x_fns <- get_attributes(x)$fns |> convert_snake_to_title_case()
y_fns <- get_attributes(y)$fns |> convert_snake_to_title_case()
df <- tibble(
walk_number = paste0("Sim ", rep(1:nw, each = length(xx)/nw)) |>
factor(levels = paste0("Sim ", 1:nw)),
x = xx,
y = yy
)
p1 <- df |>
ggplot(aes(color = walk_number)) +
facet_wrap(~ walk_number, scales = "free") +
geom_path(
aes(x = x, y = y, lwd = c(0, diff(y))),
show.legend = FALSE
) +
scale_color_viridis_d(option = "viridis") +
labs(caption = "Separate Random Walks") +
theme_void()
p2 <- df |>
ggplot(aes(color = walk_number)) +
geom_path(
aes(x = x, y = y, lwd = c(0, diff(y))),
show.legend = FALSE
) +
scale_color_viridis_d(option = "viridis") +
labs(caption = "All Random Walks Put Together by Factors") +
theme_void()
p3 <- df |>
ggplot() +
geom_path(aes(x = x, y = y, color = y, lwd = c(0, diff(y))), show.legend = FALSE) +
scale_color_viridis_c(option = "plasma") +
theme_void()
(p1 + (p2 / p3)) +
plot_annotation(
title = "Caligraphy in ggplot2 using RandomWalker",
subtitle = paste0(nw, " Random Walks with ", n, " Steps", "\n",
"Using: ", x_fns, ", ", y_fns),
caption = "All Walks Put Together Scale Color Plasma"
)library(RandomWalker)
library(dplyr)
library(ggplot2)
library(patchwork)
n <- 25
nw <- 3
x <- random_normal_walk(.num_walks = nw, .n = n, .samp = FALSE) |>
select(cum_sum_y)
y <- random_cauchy_walk(.num_walks = nw, .n = n, .samp = FALSE) |>
select(y)
xx <- predict(smooth.spline(x$cum_sum_y, spar = 0.005), seq(1, n, 0.01))$y[-1]
yy <- predict(smooth.spline(y$y, spar = 0.005), seq(1, n, 0.01))$y[-1]
x_fns <- get_attributes(x)$fns |> convert_snake_to_title_case()
y_fns <- get_attributes(y)$fns |> convert_snake_to_title_case()
df <- tibble(
walk_number = paste0("Sim ", rep(1:nw, each = length(xx)/nw)) |>
factor(levels = paste0("Sim ", 1:nw)),
x = xx,
y = yy
)
p1 <- df |>
ggplot(aes(color = walk_number)) +
facet_wrap(~ walk_number, scales = "free") +
geom_path(
aes(x = x, y = y, lwd = c(0, diff(y))),
show.legend = FALSE
) +
scale_color_viridis_d(option = "viridis") +
labs(caption = "Separate Random Walks") +
theme_void()
p2 <- df |>
ggplot(aes(color = walk_number)) +
geom_path(
aes(x = x, y = y, lwd = c(0, diff(y))),
show.legend = FALSE
) +
scale_color_viridis_d(option = "viridis") +
labs(caption = "All Random Walks Put Together by Factors") +
theme_void()
p3 <- df |>
ggplot() +
geom_path(aes(x = x, y = y, color = y, lwd = c(0, diff(y))), show.legend = FALSE) +
scale_color_viridis_c(option = "plasma") +
theme_void()
(p1 + (p2 / p3)) +
plot_annotation(
title = "Caligraphy in ggplot2 using RandomWalker",
subtitle = paste0(nw, " Random Walks with ", n, " Steps", "\n",
"Using: ", x_fns, ", ", y_fns),
caption = "All Walks Put Together Scale Color Plasma"
)Using RandomWalker and ggplot2 with patchwork to create some calligraphy ar
t.
library(RandomWalker)
library(dplyr)
library(ggplot2)
library(patchwork)
n <- 25
nw <- 3
x <- random_normal_walk(.num_walks = nw, .n = n, .samp = FALSE) |>
select(cum_sum_y)
y <- random_cauchy_walk(.num_walks = nw, .n = n, .samp = FALSE) |>
select(y)
xx <- predict(smooth.spline(x$cum_sum_y, spar = 0.005), seq(1, n, 0.01))$y[-1]
yy <- predict(smooth.spline(y$y, spar = 0.005), seq(1, n, 0.01))$y[-1]
x_fns <- get_attributes(x)$fns |> convert_snake_to_title_case()
y_fns <- get_attributes(y)$fns |> convert_snake_to_title_case()
df <- tibble(
walk_number = paste0("Sim ", rep(1:nw, each = length(xx)/nw)) |>
factor(levels = paste0("Sim ", 1:nw)),
x = xx,
y = yy
)
p1 <- df |>
ggplot(aes(color = walk_number)) +
facet_wrap(~ walk_number, scales = "free") +
geom_path(
aes(x = x, y = y, lwd = c(0, diff(y))),
show.legend = FALSE
) +
scale_color_viridis_d(option = "viridis") +
labs(caption = "Separate Random Walks") +
theme_void()
p2 <- df |>
ggplot(aes(color = walk_number)) +
geom_path(
aes(x = x, y = y, lwd = c(0, diff(y))),
show.legend = FALSE
) +
scale_color_viridis_d(option = "viridis") +
labs(caption = "All Random Walks Put Together by Factors") +
theme_void()
p3 <- df |>
ggplot() +
geom_path(aes(x = x, y = y, color = y, lwd = c(0, diff(y))), show.legend = FALSE) +
scale_color_viridis_c(option = "plasma") +
theme_void()
(p1 + (p2 / p3)) +
plot_annotation(
title = "Caligraphy in ggplot2 using RandomWalker",
subtitle = paste0(nw, " Random Walks with ", n, " Steps", "\n",
"Using: ", x_fns, ", ", y_fns),
caption = "All Walks Put Together Scale Color Plasma"
)TL;DR: Today I’m learning how to automate Excel with Python using openpyxl, and sharing my beginner-friendly notes, code, and discoveries! 🐍📊
In today’s article, I’m go over some basics on working with Excel spreadsheets using Python’s
openpyxl library. As I write this series, I’m learning right alongside you, so I’ll share what’s working for me, what’s confusing, and some handy code snippets I’ve picked up.
First, I learned that openpyxl lets you create, read, and edit Excel files (.xlsx) without needing Excel installed. That’s a huge time saver for automating boring tasks like updating prices or generating reports.
Here’s a simple example I tried for creating a new Excel file:
import openpyxl
wb = openpyxl.Workbook()
sheet = wb.active
sheet['A1'] = 'Hello, world!' # My first cell!
wb.save('hello.xlsx')
I also discovered how to load and edit existing spreadsheets, rename sheets, and save my changes:
wb = openpyxl.load_workbook('hello.xlsx')
sheet = wb.active
sheet.title = 'MySheet'
wb.save('hello_edited.xlsx')
One thing I’m practicing is using loops to update lots of rows at once. For example, if you need to update prices for certain products, you can use a dictionary and a loop way faster than doing it by hand!
PRICE_UPDATES = {'Garlic': 3.07, 'Celery': 1.19, 'Lemon': 1.27}
for row in range(2, sheet.max_row + 1):
produce = sheet.cell(row=row, column=1).value
if produce in PRICE_UPDATES:
sheet.cell(row=row, column=2).value = PRICE_UPDATES[produce]
wb.save('updated.xlsx')
Styling cells is also pretty fun and makes your spreadsheets look more professional. Here’s how I made text bold and changed font size:
from openpyxl.styles import Font
sheet['A1'].font = Font(bold=True, size=14)
And yes, you can even add formulas and charts with openpyxl! I’m still experimenting with these, but it’s amazing how much you can automate 🚀
#Python #Excel #openpyxl #LearningTogether
🔗Post: https://www.spsanderson.com/steveondata/posts/2025-09-10/Here are an audio and video overview of today's #Python blog post on using Python with #Excel
TidyDensity has been updated!
News:
TidyDensity 1.5.2
CRAN release: 2025-09-06
Breaking Changes:
Fix #521 - Fundamentally redesign of quantile_normalize() to use a more efficient algorithm. This has resulted in a breaking
change as the output is now slightly different. The new algorithm is also faster and more memory efficient.
New Features:
Fix #510 - Add parameter to tidy_mixture_density() to allow for different types of combinations, add, subtract, stack, multiply and divide.
Minor Fixes and Improvements:
None
Post: https://www.spsanderson.com/steveondata/posts/2025-09-08/
TL;DR: In today’s article, I’m learning web scraping right alongside you! 🐍✨ We’ll explore how to use Python tools like
requests, BeautifulSoup, and Selenium to grab data from websites, with simple code and clear explanations for every step. #Python #WebScraping
---
Hey everyone! In today’s article, I want to share my journey as I learn web scraping in Python. I’m not an expert yet, so I’ll explain everything in plain English and walk through each step as I figure it out myself. If you’re new to programming or web scraping, you’re in the right place.
What is Web Scraping?
Web scraping means using a program to automatically download and process content from the web. Instead of copying and pasting info by hand, you can write Python scripts to fetch and extract the data you need from websites .
Key Python Tools:
- webbrowser: Opens a web page in your browser (not for scraping, but handy for automation).
- requests: Downloads web pages and files from the internet.
- BeautifulSoup (bs4): Parses HTML so you can easily find and extract data.
- selenium: Automates a real browser, great for sites that use JavaScript or need interaction.
Example: Downloading a Web Page
import requests
res = requests.get('https://example.com')
if res.status_code == 200:
print("Success!")
print(res.text[:250]) # Print the first 250 characters
else:
print("Failed to fetch page.")
- requests.get() fetches the page.
- res.status_code checks if it worked (200 means OK).
- res.text contains the HTML content .
Parsing HTML with BeautifulSoup
from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')
title = soup.find('title').get_text()
print("Page title:", title)
- BeautifulSoup() organizes the HTML.
- find('title') grabs the <title> tag.
- get_text() gets just the text inside.
When to Use Selenium?
If a website loads data with JavaScript or needs you to click buttons or log in, use Selenium. It can control a real browser and interact with the page just like you would ,[7]].
Best Practices:
- Always check a site’s robots.txt and terms of service before scraping.
- Add delays between requests to avoid overloading servers.
- Handle errors with try/except blocks.
- Use browser developer tools (F12) to inspect HTML and find the data you want,.
Quick Tip:
To select elements in BeautifulSoup, you can use CSS selectors:
soup.select('.my-class') # All elements with class="my-class"
soup.select('#my-id') # Element with id="my-id"
And to get the text:
element = soup.select_one('p.intro')
print(element.get_text())
---
That’s a quick intro to web scraping in Python! I’m learning as I go, so if you have questions or tips, let’s help each other out. Stay tuned for more hands-on examples and projects as this series continues! 🚀
#Python #WebScraping #BeautifulSoup #Selenium
🔗 Read more: https://www.spsanderson.com/steveondata/posts/2025-09-03/I forgot to post the newest blog article i posted yesterday, i will be back on schedule now.
https://www.spsanderson.com/steveondata/
#R #RStats
Here is a list of all of my #Linux posts on my #Blog
https://www.spsanderson.com/steveondata/#category=linux
#Enjoy #Programming #Code #Technology
I am out sick for the next couple of weeks so i won’t be posting for a bit.
Today's #Python article is on Debugging. I'm learning as I write so, have a heart :)
Post: https://www.spsanderson.com/steveondata/posts/2025-08-06/
#Python #Debugging #Blog #Technology #Learning
Today's post is on finding row numbers of a data.frame in #R
Post: https://www.spsanderson.com/steveondata/posts/2025-08-04/
#RStats #R #Blog #Code
In today's article I talked into organizing files with Python using the os and shutil modules! 🐍 I learned how to create directories, copy files, move and rename them. Here’s a small code snippet:
import os
import shutil
# Create a new folder (if it doesn't exist)
os.makedirs('my_new_folder', exist_ok=True)
# Copy a file into the new folder
shutil.copy('example.txt', 'my_new_folder/example_copy.txt')
# Move (or rename) a file into the new folder
shutil.move('temp.txt', 'my_new_folder/temp.txt')
I'm still learning as I write this series, so please bear with me if I make any mistakes. I encourage you to try these examples on your own (just be sure to work with test files first!).
Post: https://www.spsanderson.com/steveondata/posts/2025-07-30/Here is a link to today's blog post on adding a totals row to a
data.frame
Post: https://www.spsanderson.com/steveondata/posts/2025-07-28/