├── README.md ├── animated_engagement ├── animated_engagement_charts.R ├── rickydata_top_followers.gif └── rickydata_top_following.gif ├── data_analysis └── README.md ├── lens_advanced_search └── README.md ├── lens_trends └── README.md ├── lens_user_word_cloud └── README.md └── timeline_summarizer └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Lens Data Tools by [rickydata.lens](https://lenster.xyz/u/rickydata) 2 | 3 | ## May 6, 2024 4 | 5 | ### Build Your Own Gallery 6 | 7 | Configure your own art gallery based on a search term and maximum price, and find new pieces to collect on Lens. 8 | 9 | image 10 | 11 | 12 | - Post: [https://lenster.xyz/posts/0x5bfc-0x01e0](https://hey.xyz/posts/0x0102cc-0x0319) 13 | 14 | - Tool: [https://www.voxels.com/play?coords=N@6889W,38S](https://www.voxels.com/play?coords=N@6889W,38S) 15 | 16 | 17 | ## May 17, 2023 18 | 19 | ### Animated Visualization of Account Interactions Leaderboard 20 | 21 | Animated charts to view the top profiles that have engaged with you over the past year. This is the only one on this list which isn't a publicly deployed tool, because it still needs to be optimized, and generating the .gif can take a long time (a one year period tends to be about 2,000 images/charts that are then put together. The code itself is [all publicly available here](https://github.com/ries9112/LensDataTools/blob/main/animated_engagement/animated_engagement_charts.R) and can be used locally by anyone who provides their own Google account (the script should walk users through an interactive login without worrying about tokens and security). 22 | 23 | | [![rickydata top following](https://github.com/ries9112/LensDataTools/blob/main/animated_engagement/rickydata_top_following.gif?raw=true)](https://github.com/ries9112/LensDataTools/blob/main/animated_engagement/rickydata_top_following.gif?raw=true) | [![rickydata top followers](https://github.com/ries9112/LensDataTools/blob/main/animated_engagement/rickydata_top_followers.gif?raw=true)](https://github.com/ries9112/LensDataTools/blob/main/animated_engagement/rickydata_top_followers.gif?raw=true) | 24 | |---|---| 25 | 26 | 27 | - Post: https://lenster.xyz/posts/0x5bfc-0x01e0 28 | 29 | - Code: https://github.com/ries9112/LensDataTools/blob/main/animated_engagement/animated_engagement_charts.R 30 | 31 | - Tool: TBD 32 | 33 | 34 | ## April 17, 2023 35 | 36 | ### Timeline Summarizer 37 | 38 | Summarizes the key highlights from someone's feed over a specified period of time and reads them out loud. 39 | 40 | 41 | timeline summary 42 | 43 | 44 | - Post: https://lenster.xyz/posts/0x0102cc-0x01ac 45 | 46 | - Tool: https://predictcrypto.shinyapps.io/timeline-summary/ 47 | 48 | 49 | ### Content Discovery 50 | 51 | Find content you haven't interacted with yet which you may find interesting. Finds which accounts you interact with a lot and uses that to guide which content you may find interesting. 52 | 53 | 54 | content discovery 55 | 56 | 57 | 58 | - Post: https://lenster.xyz/posts/0x0102cc-0x01a9 59 | 60 | - Tool: https://predictcrypto.shinyapps.io/content-discovery/ 61 | 62 | 63 | 64 | ## April 14, 2023 65 | 66 | ### Lens Advanced Search 67 | 68 | A tool to help find specific posts based on a number of optional criteria. 69 | 70 | 71 | advanced search 72 | 73 | 74 | - Post: https://lenster.xyz/posts/0x0102cc-0x018b 75 | 76 | - Tool: https://predictcrypto.shinyapps.io/LensAdvancedSearch/ 77 | 78 | 79 | ## March 29th, 2023 80 | 81 | User notifications by day. 82 | 83 | 84 | user notifications 85 | 86 | 87 | - Post: https://lenster.xyz/posts/0x0102cc-0x0164 88 | 89 | - Tool: https://predictcrypto.shinyapps.io/lens_user_notifications/ 90 | 91 | 92 | 93 | ## March 26th, 2023 94 | 95 | ### Lens Trends Dashboard 96 | 97 | A dashboard used to look up any word and see how many posts that word appeared in by day. 98 | 99 | 100 | Lens Trends 101 | 102 | 103 | - Post: https://lenster.xyz/posts/0x0102cc-0x012f 104 | 105 | - Tool: https://predictcrypto.shinyapps.io/LensTrends/ 106 | 107 | 108 | ### Lens User Word Cloud Generator 109 | 110 | Generates a word cloud for any Lens user using all the content from all the posts by that user. 111 | 112 | 113 | word cloud generator 114 | 115 | 116 | - Post: https://lenster.xyz/posts/0x0102cc-0x0110 117 | 118 | - Tool: https://lens-wordcloud.streamlit.app/ 119 | 120 | 121 | ## March 17th, 2023 122 | 123 | ### Lens User Followers Trend & Forecast 124 | 125 | Shows the growth in followrs for a user over time and produces a forecast. 126 | 127 | 128 | User followers trend and forecast 129 | 130 | 131 | - Post: https://lenster.xyz/posts/0x0102cc-0xe6 132 | 133 | - Tool: https://predictcrypto.shinyapps.io/lens_user_stats/ 134 | 135 | 136 | ## November 8th, 2022 137 | 138 | ### Engagement on Lens vs. Twitter 139 | 140 | Tool to show the number of likes a user tends to receive on Lens vs. their Twitter proile (requires the user to have linked their twitter on Lens). 141 | 142 | 143 | Engagement on Lens vs Twitter 144 | 145 | 146 | - Post: https://lenster.xyz/posts/0x0102cc-0x43 147 | 148 | - Tool: https://predictcrypto.shinyapps.io/lens_engagement/ 149 | 150 | 151 | -------------------------------------------------------------------------------- /animated_engagement/animated_engagement_charts.R: -------------------------------------------------------------------------------- 1 | library(bigrquery) 2 | library(DBI) 3 | library(tidyverse) 4 | library(gganimate) 5 | library(scales) 6 | library(magick) 7 | library(ggdark) 8 | library(cowplot) 9 | 10 | 11 | # import lens logo to add to plots 12 | lens_png = image_read("lens_logo.png") 13 | 14 | 15 | run_for_user = function(current_handle = 'rickydata.lens'){ 16 | # connect to bigquery 17 | bquery_con <- dbConnect( 18 | bigrquery::bigquery(), 19 | project = "lens-public-data", 20 | dataset = "polygon", 21 | billing = "mlflow-291816" 22 | ) 23 | 24 | # query for account id first 25 | account_id = paste0("select 26 | profile_id, 27 | owned_by, 28 | handle, 29 | profile_picture_s3_url 30 | from `lens-public-data.polygon.public_profile` 31 | where handle = '",current_handle,"' 32 | limit 1") 33 | 34 | # Download data 35 | account_id = dbGetQuery(bquery_con, account_id)$profile_id 36 | 37 | # query 38 | sql_query = paste0("WITH notification_data AS ( 39 | SELECT 40 | TIMESTAMP_TRUNC(notification_action_date, DAY) AS date, 41 | notification_receiving_profile_id, 42 | COALESCE(notification_sender_wallet_address, notification_sender_profile_id) AS sender_id, 43 | COUNT(*) AS count 44 | FROM `lens-public-data.polygon.public_notification` 45 | WHERE notification_receiving_profile_id = '",account_id,"' 46 | GROUP BY date, notification_receiving_profile_id, sender_id 47 | ), 48 | calendar AS ( 49 | SELECT DISTINCT 50 | TIMESTAMP_TRUNC(notification_action_date, DAY) AS date 51 | FROM `lens-public-data.polygon.public_notification` 52 | WHERE notification_receiving_profile_id = '",account_id,"' 53 | ), 54 | senders AS ( 55 | SELECT DISTINCT 56 | COALESCE(notification_sender_wallet_address, notification_sender_profile_id) AS sender_id 57 | FROM `lens-public-data.polygon.public_notification` 58 | WHERE notification_receiving_profile_id = '",account_id,"' 59 | ), 60 | cumulative_interactions AS ( 61 | SELECT 62 | calendar.date, 63 | '",account_id,"' AS notification_receiving_profile_id, 64 | senders.sender_id, 65 | COALESCE( 66 | SUM( 67 | COALESCE(notification_data.count, 0) 68 | ) OVER ( 69 | PARTITION BY senders.sender_id 70 | ORDER BY calendar.date ASC 71 | ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 72 | ), 73 | 0 74 | ) AS cumulative_interaction_count 75 | FROM calendar 76 | CROSS JOIN senders 77 | LEFT JOIN notification_data 78 | ON calendar.date = notification_data.date 79 | AND senders.sender_id = notification_data.sender_id 80 | ) 81 | SELECT 82 | cumulative_interactions.date, 83 | cumulative_interactions.notification_receiving_profile_id, 84 | cumulative_interactions.sender_id, 85 | cumulative_interactions.cumulative_interaction_count, 86 | public_profile.profile_id, 87 | public_profile.owned_by, 88 | public_profile.handle, 89 | public_profile.profile_picture_s3_url 90 | FROM cumulative_interactions 91 | JOIN `lens-public-data.polygon.public_profile` AS public_profile 92 | ON cumulative_interactions.sender_id = public_profile.profile_id 93 | OR cumulative_interactions.sender_id = public_profile.owned_by 94 | ORDER BY cumulative_interactions.date DESC") 95 | 96 | 97 | # Download data 98 | data = dbGetQuery(bquery_con, sql_query) 99 | 100 | # disconnect 101 | dbDisconnect(bquery_con) 102 | 103 | 104 | 105 | # GREAT EXAMPLE: https://towardsdatascience.com/create-animated-bar-charts-using-r-31d09e5841da 106 | 107 | # remove engagement by user themselves (for example responding to comments) 108 | data = filter(data, notification_receiving_profile_id != sender_id, owned_by != sender_id) 109 | 110 | 111 | # calculate rankings 112 | data_formatted <- data %>% 113 | filter(cumulative_interaction_count > 5) %>% 114 | arrange(date, desc(cumulative_interaction_count), handle) %>% # Order by date, count and also handle 115 | group_by(date) %>% 116 | mutate(rank = dense_rank(desc(cumulative_interaction_count) + row_number() / 1000), 117 | Value_rel = cumulative_interaction_count / cumulative_interaction_count[rank == 1], 118 | Value_lbl = cumulative_interaction_count) %>% 119 | group_by(handle) %>% 120 | filter(rank <= 10) %>% 121 | ungroup() 122 | 123 | staticplot <- ggplot(data_formatted, aes(rank, group = handle, 124 | fill = as.factor(handle), color = as.factor(handle))) + 125 | geom_tile(aes(y = cumulative_interaction_count/2, 126 | height = cumulative_interaction_count, 127 | width = 0.9), alpha = 0.8, color = NA) + 128 | geom_text(aes(y = 0, label = paste(handle, " ")), vjust = 0.2, hjust = 1) + 129 | geom_text(aes(y = round(cumulative_interaction_count), 130 | label = round(Value_lbl), 131 | hjust = 0), 132 | size = 3.5, fontface = "bold") + 133 | coord_flip(clip = "off", expand = FALSE) + 134 | scale_x_reverse() + 135 | guides(color = FALSE, fill = FALSE) + 136 | theme(axis.line=element_blank(), 137 | axis.text.x=element_blank(), 138 | axis.text.y=element_blank(), 139 | axis.ticks=element_blank(), 140 | axis.title.x=element_blank(), 141 | axis.title.y=element_blank(), 142 | legend.position="none", 143 | panel.background=element_blank(), 144 | panel.border=element_blank(), 145 | panel.grid.major=element_blank(), 146 | panel.grid.minor=element_blank(), 147 | panel.grid.major.x = element_line(size=.1, color="grey"), 148 | panel.grid.minor.x = element_line(size=.1, color="grey"), 149 | plot.title=element_text(size=20, hjust=0.5, face="bold"), 150 | plot.subtitle=element_text(size=18, hjust=0.5, face="italic"), 151 | plot.caption =element_text(size=8, hjust=0.5, face="italic"), 152 | plot.background=element_blank(), 153 | plot.margin = margin(2, 2, 2, 4, "cm")) + 154 | labs(title = paste0("Top Profiles Engaging With ",current_handle), 155 | subtitle = "Through: {closest_state}", 156 | caption = "Made by rickydata.lens") + 157 | theme(plot.caption = element_text(size = 16, hjust = 1, vjust = 1, face = "bold")) 158 | # dark_theme_minimal() 159 | 160 | # Add logo (makes it super slow!) 161 | # staticplot <- ggdraw() + 162 | # draw_plot(staticplot) + 163 | # draw_image(lens_png, x = 0.42, y = 0.32, scale = 0.2) 164 | 165 | 166 | anim = staticplot + transition_states(date, transition_length = 9000, state_length = 50) + 167 | view_follow(fixed_x = TRUE) + 168 | labs(title = paste0("Top Profiles Engaging With ",current_handle), 169 | caption = "Made by rickydata.lens") 170 | 171 | 172 | # show but don't save: 173 | # animate(anim, length(unique(data$date)), fps = 20, width = 800, height = 670, 174 | # duration = 90, end_pause = 60, res = 100) 175 | 176 | 177 | # For GIF 178 | animate(anim, length(unique(data$date)), fps = 20, width = 800, height = 670, 179 | duration = 90, end_pause = 0, res = 100, # can lower resolution to upload image if needed 180 | renderer = gifski_renderer(paste0(current_handle,".gif"))) 181 | 182 | # CONVERT MANUALLY HERE IF LARGER THAN 10MB: https://convertio.co/gif-mp4/ 183 | 184 | 185 | # For MP4 (doesn't work) 186 | # library(av) 187 | # b <- animate(anim, length(unique(data$date)), fps = 20, width = 800, height = 670, 188 | # duration = 90, end_pause = 60, res = 100, renderer = av_renderer()) 189 | # anim_save("rickydata.mp4", b) 190 | 191 | 192 | 193 | 194 | 195 | 196 | # Next: make a similar one showing most content I have interacted with myself 197 | 198 | 199 | 200 | 201 | # Next: make a similar one showing most content I have interacted with myself 202 | 203 | 204 | } 205 | 206 | # Run script for a user: 207 | # run_for_user('punkess.lens') 208 | # run_for_user('stani.lens') # NEED TO COME BACK TO STANI - TOO MUCH DATA 209 | # run_for_user('mazemari.lens') 210 | # run_for_user('carlosbeltran.lens') 211 | # run_for_user('larryscruff.lens') 212 | # run_for_user('kipto.lens') 213 | # run_for_user('jovana_kvrzic.lens') 214 | # run_for_user('nader.lens') 215 | # run_for_user('gotenks.lens') 216 | # run_for_user('0xzelda.lens') 217 | run_for_user('bennyj504.lens') 218 | 219 | # After: convert to MP4 here: https://convertio.co/gif-mp4/ 220 | 221 | 222 | 223 | 224 | 225 | # Alternative query which gets output much lower so I don't need to download millions of rows of data (could be useful if I made it into an app): 226 | 227 | # sql_query = paste0(" 228 | # WITH notification_data AS ( 229 | # SELECT 230 | # TIMESTAMP_TRUNC(notification_action_date, DAY) AS date, 231 | # notification_receiving_profile_id, 232 | # COALESCE(notification_sender_wallet_address, notification_sender_profile_id) AS sender_id, 233 | # COUNT(*) AS count 234 | # FROM `lens-public-data.polygon.public_notification` 235 | # WHERE notification_receiving_profile_id = '", account_id, "' 236 | # GROUP BY date, notification_receiving_profile_id, sender_id 237 | # ), 238 | # calendar AS ( 239 | # SELECT DISTINCT 240 | # TIMESTAMP_TRUNC(notification_action_date, DAY) AS date 241 | # FROM `lens-public-data.polygon.public_notification` 242 | # WHERE notification_receiving_profile_id = '", account_id, "' 243 | # ), 244 | # senders AS ( 245 | # SELECT DISTINCT 246 | # COALESCE(notification_sender_wallet_address, notification_sender_profile_id) AS sender_id 247 | # FROM `lens-public-data.polygon.public_notification` 248 | # WHERE notification_receiving_profile_id = '", account_id, "' 249 | # ), 250 | # cumulative_interactions AS ( 251 | # SELECT 252 | # calendar.date, 253 | # '", account_id, "' AS notification_receiving_profile_id, 254 | # senders.sender_id, 255 | # COALESCE( 256 | # SUM( 257 | # COALESCE(notification_data.count, 0) 258 | # ) OVER ( 259 | # PARTITION BY senders.sender_id 260 | # ORDER BY calendar.date ASC 261 | # ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 262 | # ), 263 | # 0 264 | # ) AS cumulative_interaction_count 265 | # FROM calendar 266 | # CROSS JOIN senders 267 | # LEFT JOIN notification_data 268 | # ON calendar.date = notification_data.date 269 | # AND senders.sender_id = notification_data.sender_id 270 | # ), 271 | # filtered_data AS ( 272 | # SELECT 273 | # cumulative_interactions.date, 274 | # cumulative_interactions.notification_receiving_profile_id, 275 | # cumulative_interactions.sender_id, 276 | # cumulative_interactions.cumulative_interaction_count, 277 | # public_profile.profile_id, 278 | # public_profile.owned_by, 279 | # public_profile.handle, 280 | # public_profile.profile_picture_s3_url 281 | # FROM cumulative_interactions 282 | # JOIN `lens-public-data.polygon.public_profile` AS public_profile 283 | # ON cumulative_interactions.sender_id = public_profile.profile_id 284 | # OR cumulative_interactions.sender_id = public_profile.owned_by 285 | # ), 286 | # processed_data AS ( 287 | # SELECT 288 | # filtered_data.*, 289 | # ROW_NUMBER() OVER (PARTITION BY filtered_data.date ORDER BY filtered_data.cumulative_interaction_count DESC, filtered_data.handle ASC) AS row_num 290 | # FROM filtered_data 291 | # WHERE filtered_data.notification_receiving_profile_id <> filtered_data.sender_id 292 | # AND filtered_data.owned_by <> filtered_data.sender_id 293 | # ), 294 | # ranked_data AS ( 295 | # SELECT 296 | # processed_data.*, 297 | # DENSE_RANK() OVER (PARTITION BY processed_data.date ORDER BY processed_data.cumulative_interaction_count DESC, processed_data.handle ASC) AS rank 298 | # FROM processed_data 299 | # ) 300 | # SELECT 301 | # ranked_data.date, 302 | # ranked_data.notification_receiving_profile_id, 303 | # ranked_data.sender_id, 304 | # ranked_data.cumulative_interaction_count, 305 | # ranked_data.profile_id, 306 | # ranked_data.owned_by, 307 | # ranked_data.handle, 308 | # ranked_data.profile_picture_s3_url, 309 | # ranked_data.rank, 310 | # ranked_data.cumulative_interaction_count / MAX(CASE WHEN ranked_data.rank = 1 THEN ranked_data.cumulative_interaction_count END) OVER (PARTITION BY ranked_data.date) AS Value_rel, 311 | # ranked_data.cumulative_interaction_count AS Value_lbl 312 | # FROM ranked_data 313 | # WHERE ranked_data.row_num <= 10 314 | # ORDER BY ranked_data.date DESC") 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | # Next query - show your own engagement with other users ------------------ 325 | 326 | 327 | run_for_user_interactions = function(current_handle = 'rickydata.lens'){ 328 | # connect to bigquery 329 | bquery_con <- dbConnect( 330 | bigrquery::bigquery(), 331 | project = "lens-public-data", 332 | dataset = "polygon", 333 | billing = "mlflow-291816" 334 | ) 335 | 336 | # query for account id first 337 | account_id = paste0("select 338 | profile_id, 339 | owned_by, 340 | handle, 341 | profile_picture_s3_url 342 | from `lens-public-data.polygon.public_profile` 343 | where handle = '",current_handle,"' 344 | limit 1") 345 | 346 | # Download data 347 | account_id = dbGetQuery(bquery_con, account_id)$profile_id 348 | 349 | # query 350 | sql_query = paste0("WITH notification_data AS ( 351 | SELECT 352 | TIMESTAMP_TRUNC(notification_action_date, DAY) AS date, 353 | notification_sender_profile_id, 354 | notification_receiving_profile_id AS receiver_id, 355 | COUNT(*) AS count 356 | FROM `lens-public-data.polygon.public_notification` 357 | WHERE notification_sender_profile_id = '",account_id,"' 358 | GROUP BY date, notification_sender_profile_id, receiver_id 359 | ), 360 | calendar AS ( 361 | SELECT DISTINCT 362 | TIMESTAMP_TRUNC(notification_action_date, DAY) AS date 363 | FROM `lens-public-data.polygon.public_notification` 364 | WHERE notification_sender_profile_id = '",account_id,"' 365 | ), 366 | receivers AS ( 367 | SELECT DISTINCT 368 | notification_receiving_profile_id AS receiver_id 369 | FROM `lens-public-data.polygon.public_notification` 370 | WHERE notification_sender_profile_id = '",account_id,"' 371 | ), 372 | cumulative_interactions AS ( 373 | SELECT 374 | calendar.date, 375 | '",account_id,"' AS notification_sender_profile_id, 376 | receivers.receiver_id, 377 | COALESCE( 378 | SUM( 379 | COALESCE(notification_data.count, 0) 380 | ) OVER ( 381 | PARTITION BY receivers.receiver_id 382 | ORDER BY calendar.date ASC 383 | ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 384 | ), 385 | 0 386 | ) AS cumulative_interaction_count 387 | FROM calendar 388 | CROSS JOIN receivers 389 | LEFT JOIN notification_data 390 | ON calendar.date = notification_data.date 391 | AND receivers.receiver_id = notification_data.receiver_id 392 | ) 393 | SELECT 394 | cumulative_interactions.date, 395 | cumulative_interactions.notification_sender_profile_id, 396 | cumulative_interactions.receiver_id, 397 | cumulative_interactions.cumulative_interaction_count, 398 | public_profile.profile_id, 399 | public_profile.owned_by, 400 | public_profile.handle, 401 | public_profile.profile_picture_s3_url 402 | FROM cumulative_interactions 403 | JOIN `lens-public-data.polygon.public_profile` AS public_profile 404 | ON cumulative_interactions.receiver_id = public_profile.profile_id 405 | OR cumulative_interactions.receiver_id = public_profile.owned_by 406 | ORDER BY cumulative_interactions.date DESC") 407 | 408 | 409 | 410 | # Download data 411 | data = dbGetQuery(bquery_con, sql_query) 412 | 413 | # disconnect 414 | dbDisconnect(bquery_con) 415 | 416 | # remove engagement by user themselves 417 | data = filter(data, notification_sender_profile_id != receiver_id, owned_by != receiver_id) 418 | 419 | # calculate rankings 420 | data_formatted <- data %>% 421 | filter(cumulative_interaction_count > 5) %>% 422 | arrange(date, desc(cumulative_interaction_count), handle) %>% # Order by date, count and also handle 423 | group_by(date) %>% 424 | mutate(rank = dense_rank(desc(cumulative_interaction_count) + row_number() / 1000), 425 | Value_rel = cumulative_interaction_count / cumulative_interaction_count[rank == 1], 426 | Value_lbl = cumulative_interaction_count) %>% 427 | group_by(handle) %>% 428 | filter(rank <= 10) %>% 429 | ungroup() 430 | 431 | staticplot <- ggplot(data_formatted, aes(rank, group = handle, 432 | fill = as.factor(handle), color = as.factor(handle))) + 433 | geom_tile(aes(y = cumulative_interaction_count/2, 434 | height = cumulative_interaction_count, 435 | width = 0.9), alpha = 0.8, color = NA) + 436 | geom_text(aes(y = 0, label = paste(handle, " ")), vjust = 0.2, hjust = 1) + 437 | geom_text(aes(y = round(cumulative_interaction_count), 438 | label = round(Value_lbl), 439 | hjust = 0), 440 | size = 3.5, fontface = "bold") + 441 | coord_flip(clip = "off", expand = FALSE) + 442 | scale_x_reverse() + 443 | guides(color = FALSE, fill = FALSE) + 444 | theme(axis.line=element_blank(), 445 | axis.text.x=element_blank(), 446 | axis.text.y=element_blank(), 447 | axis.ticks=element_blank(), 448 | axis.title.x=element_blank(), 449 | axis.title.y=element_blank(), 450 | legend.position="none", 451 | panel.background=element_blank(), 452 | panel.border=element_blank(), 453 | panel.grid.major=element_blank(), 454 | panel.grid.minor=element_blank(), 455 | panel.grid.major.x = element_line(size=.1, color="grey"), 456 | panel.grid.minor.x = element_line(size=.1, color="grey"), 457 | plot.title=element_text(size=20, hjust=0.5, face="bold"), 458 | plot.subtitle=element_text(size=18, hjust=0.5, face="italic"), 459 | plot.caption =element_text(size=8, hjust=0.5, face="italic"), 460 | plot.background=element_blank(), 461 | plot.margin = margin(2, 2, 2, 4, "cm")) + 462 | labs(title = paste0("Top Profiles ",current_handle," Engages With"), 463 | subtitle = "Through: {closest_state}", 464 | caption = "Made by rickydata.lens") + 465 | theme(plot.caption = element_text(size = 16, hjust = 1, vjust = 1, face = "bold")) 466 | 467 | anim = staticplot + transition_states(date, transition_length = 9000, state_length = 50) + 468 | view_follow(fixed_x = TRUE) + 469 | labs(title = paste0("Top Profiles ",current_handle," Engages With"), 470 | caption = "Made by rickydata.lens") 471 | 472 | # For GIF 473 | animate(anim, length(unique(data$date)), fps = 20, width = 800, height = 670, 474 | duration = 90, end_pause = 0, res = 100, # can lower resolution to upload image if needed 475 | renderer = gifski_renderer(paste0(current_handle,"_interactions.gif"))) 476 | } 477 | 478 | 479 | # Run script for a user: 480 | # run_for_user_interactions('stani.lens') 481 | # run_for_user_interactions('chaoticmonk.lens') 482 | # run_for_user_interactions('punkess.lens') 483 | # run_for_user('mazemari.lens') 484 | run_for_user('carlosbeltran.lens') 485 | # run_for_user('larryscruff.lens') 486 | # run_for_user('kipto.lens') 487 | # run_for_user('jovana_kvrzic.lens') 488 | # run_for_user('nader.lens') 489 | # run_for_user('gotenks.lens') 490 | # run_for_user('0xzelda.lens') 491 | # run_for_user('bennyj504.lens') 492 | 493 | -------------------------------------------------------------------------------- /animated_engagement/rickydata_top_followers.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ries9112/LensDataTools/c11b53edc4fce76107176bb33797656335942bdc/animated_engagement/rickydata_top_followers.gif -------------------------------------------------------------------------------- /animated_engagement/rickydata_top_following.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ries9112/LensDataTools/c11b53edc4fce76107176bb33797656335942bdc/animated_engagement/rickydata_top_following.gif -------------------------------------------------------------------------------- /data_analysis/README.md: -------------------------------------------------------------------------------- 1 | # Misc Data Analysis 2 | 3 | ## March 26th, 2023 4 | 5 | ### Word cloud based on all posts (through March 26th, 2023) 6 | 7 | - Post: https://lenster.xyz/posts/0x0102cc-0x0105 8 | 9 | ### Best times to maximize engagement (through March 26th, 2023) 10 | 11 | - Post: https://lenster.xyz/posts/0x0102cc-0x0136 12 | -------------------------------------------------------------------------------- /lens_advanced_search/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lens_trends/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lens_user_word_cloud/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /timeline_summarizer/README.md: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------