Report on Ball Machine Consultation
Report Brief
In the Committee Meeting of 8th August 2025 an item was discussed during the ‘Treasurer’s Report’: “Suggestion of new ball machine discussed – all in agreement this would be a positive use of income.” Darren Garside was actioned to: “look into ball machine purchase and feedback to committee in interim”.
As a consequence of an informal consultation with coaching colleagues and the general membership, this report summarises my findings and recommendations. After the summary section immediately below, the rest of the report details the evidence and interpretations and in appendices provides details of methodology and analysis.
Summary
Coaches and members who represent the Club in the higher divisions do not perceive a need for a new ball machine given the nature and system of player development, epitomised by many successful years of the Club’s individual players and teams.
General members (representative and recreational players) are generally positive about a new ball machine but have concerns whether it will benefit all members equally. There is a gender aspect to these opinions.
Recommendation(s)
A new ball machine be purchased, primarily for the use of lower team and recreational members.
Criteria for selecting in order of decreasing importance should be: reliablity, usability, cost, then functionality
There should be a training and induction offer and support materials to make the ball machine accessible for all adult players.
The Committee to be clear to Members about source of funding and opportunity costs of making this decision and this report be made available to members.
Evidence and interpretation
Coaches’ evidence
Response to the survey was limited but the sentiments were clear.1
I have been coaching at the club for almost 10 years and can safely [say] a ball machine, whether it be the newest of the new or the oldest of the old, will never get used. A ball machine, from a coaching standpoint, fails to exactly replicate the variability and unpredictability a rally with another player has. Coupled with the time taken to setup, put away and the potential of only being able to use certain balls in the machine makes it much more of a hassle to use for no benefit. Hence, a ball machine hasn’t been used at a coaching session in my entire time at the club - and I have worked alongside one of Scotland’s most well renowned and best coaches for those 10 years, who also doesn’t use it. I appreciate the opportunity to share my thoughts. Cheers, [name redacted].
and
The ball machine is only useful for drilling at a push. In a match you don’t face the same ball twice and a ball machine simply does not give you that. It’s better to just have hitting partners. The club in my opinion should not be spending a large amount of money. I’m a coach and even for feeding I don’t use it as it often doesn’t give my players the exact shot that I want to work with them. A very small percentage of the club actually use it and to me a ball machine is a waste of time.
Members’ survey
Approximately 10% of the membership responded (n=25) which is within expectations. Except for clearly negative experiences with the current ball machine, there was no overwhelming consensus when the responses were examined as a whole. Discernible positions emerge once contextual factors are taken into account.
Contextual data
Sentiment analysis
The wordcloud below speaks for itself and provides contextual detail for the negative ratings.
The following table uses an algorithm to rate the comments for positive/negative sentiment. It is significant that of the four negatively rated comments, three are attributable to ‘Women D2-D5’ respondents.
| Comments | Sentiment Score |
|---|---|
| I haven’t used the ball machine therefore for Q3 it was difficult to rate my experience | -0.5 |
| We are in desperate need of a new ball machine. If we had a reliable modern machine then people would use it and develop their game, especially the lower ranked players. Please invest in this now | -0.13 |
| I feel there is other priorities within the club that we should be looking to improve rather than spending money on a ball machine that will only be used by a few members. | -0.11 |
| New ball machine may only be used by a small minority. | -0.04 |
| I would definitely use a ball machine if I thought it would be reliable | 0 |
| Battery life not long enough. | 0.01 |
| It desperately needs replaced. I’d be down practising more if it was a better set up with the machine. | 0.06 |
| The ball machine is only useful for drilling at a push. In a match you don’t face the same ball twice and a ball machine simply does not give you that. It’s better to just have hitting partners. The club in my opinion should not be spending a large amount of money. I’m a coach and even for feeding I don’t use it as it often doesn’t give my players the exact shot that I want to work with them. A very small percentage of the club actually use it and to me a ball machine is a waste of time. | 0.07 |
| I had been using the current ball on a regular basis but stopped because it was so unreliable. Attempts have been made to improve it but it isn’t fully functional because it’s old. I would LOVE to have a new machine. It would really help my game and I would use it often. I think the club needs to have a new and reliable ball machine. | 0.08 |
| The current one runs out of battery too quickly - we need a new one | 0.16 |
| No explanation has been given that we are looking to upgrade the ball machine. The purpose of this survey should be to ascertain who will be interested in using a ball machine if we upgrade our existing one regardless of whether you represent KTC in the leagues or not. | 0.25 |
| Would be more likely to use a more modern ball machine | 0.3 |
| I would love the club to get a new, reliable ball machine. | 0.32 |
| The ball machine is a great tool but it’s at the point where it’s not really serving that purpose any more. It’s used by quite a lot of members - and I’m sure more would use it if it was known to be reliable and useful. | 0.42 |
If the club were to go forward with a purchase then the following diagram indicates the members’ preferences for functional priorities.
Technical Appendix
Methodology
The consultation was informal without reference to establised academic practice in survey design. The aim was to gather sentiment and contextual information given that the Committee has already strongly endorsed the idea. Three responses, all in ‘Womens D2-D5’ category questioned the premises of the survey and/or priorities. Weight has been given to this observation in the Report’s recommendations.
Analysis code
The majority of the analysis was conducted in ‘R’ with the rest in Python. ‘R’ is a free, open-source programming language specifically designed for statistical analysis, data visualization, and data science, and, it is claimed, a powerful tool for turning complex data into clear insights.
require(tidyverse)
ktc.df.1 <- read_csv("~/src/Kilmarnock Tennis Club Ball Machine Feedback(OfficeForms Table).csv")
# View(ktc.df.1)
# rename all cols to something more easy to refer to
colnames(ktc.df.1) <- c("id", "used", "3.1", "3.2", "3.3", "overall_rating", "features", "segment", "comment")
# data wrangling to manage phrases in '3 words'
# For the following rows c(5:7, 12, 14, 16, 19:20, 22) concatenate cols 3.1:3.3 together into column 3.1. The remaining rows should be unchanged
ktc.df.2 <- ktc.df.1 %>%
mutate(
`3.1` = ifelse(row_number() %in% c(5:7, 12, 14, 16, 19:20, 22),
paste(`3.1`, `3.2`, `3.3`, sep = " "),
`3.1`),
`3.2` = ifelse(row_number() %in% c(5:7, 12, 14, 16, 19:20, 22),
NA_character_,
`3.2`),
`3.3` = ifelse(row_number() %in% c(5:7, 12, 14, 16, 19:20, 22),
NA_character_,
`3.3`)
)#%pip install textblob
#%pip install pandas
import pandas as pd
from textblob import TextBlob
surveyData = pd.read_csv("~/src/Kilmarnock Tennis Club Ball Machine Feedback(OfficeForms Table).csv")
# rename 'Any other comments?' column to 'comments' for ease of use
surveyData = surveyData.rename(columns={'Any other comments or feedback?': 'comments'})
# drop rows with NaN in 'comments' column
surveyData = surveyData.dropna(subset=['comments'])
# reset index
surveyData = surveyData.reset_index(drop=True)
# function to get sentiment score
def get_sentiment(text):
blob = TextBlob(text)
return blob.sentiment.polarity # returns a value between -1.0 (negative) and 1.0 (positive)
# apply function to 'comments' column and create new 'sentiment_score' column
surveyData['sentiment_score'] = surveyData['comments'].apply(get_sentiment)
# save to new Excel file
surveyData.to_csv("../src/KTC_members_survey_with_sentiment.csv", index=False)ktc.df2.used <- ggplot(ktc.df.2, aes(x=used)) +
geom_bar() +
xlab("Respondents who have used ball machine") +
ylab("Count")
ktc.df.2.segment <- ggplot(ktc.df.2, aes(x = segment, fill = segment)) +
geom_bar() +
coord_polar(theta = "x") +
labs(title = "Who responded?")
ktc.df.2.segment
ktc.df.2.overall_rating <- ggplot(ktc.df.2, aes(x=overall_rating)) +
geom_bar() +
labs(title="Rating of experience using existing ball machine", subtitle="1=lowest, 5=highest", x="Rating" , y="Count")
ktc.df.2.overall_rating# We need a word cloud for ktf.df.2[3.1:3.3] removing stop words.
library(wordcloud)
library(tm)
# Combine the three columns into one
phrases <- na.omit(c(ktc.df.2$`3.1`, ktc.df.2$`3.2`, ktc.df.2$`3.3`))
# Create a text corpus
corpus <- Corpus(VectorSource(phrases))
# Clean the text data
corpus <- tm_map(corpus, content_transformer(tolower))
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, removeNumbers)
corpus <- tm_map(corpus, removeWords, stopwords("english"))
# Create a term-document matrix
tdm <- TermDocumentMatrix(corpus)
tdm_matrix <- as.matrix(tdm)
# Calculate word frequencies
word_freqs <- sort(rowSums(tdm_matrix), decreasing = TRUE)
# Create a data frame with words and their frequencies
word_freqs_df <- data.frame(word = names(word_freqs), freq = word_freqs)
# Generate the word cloud
set.seed(1234) # For reproducibility
wordcloud(words = word_freqs_df$word, freq = word_freqs_df$freq, min.freq = 1,
max.words=100, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))ktc.df.3 <- read_csv("~/src/KTC_members_survey_with_sentiment.csv",
col_types = cols(`Have you used the current ball machine?` = col_skip(),
`What three words would you use to describe your experience with the current ball` = col_skip(),
`What three words would you use to describe your experience with the current ba.1` = col_skip(),
`What three words would you use to describe your experience with the current ba.2` = col_skip(),
`How would you rate your overall experience with the current ball machine?` = col_skip(),
`What would be the most important features of a new ball machine for you? Drag to order with most important first.` = col_skip(),
`Do you represent the club in competitions?` = col_skip()))
# Display $comments and $sentiment_score in ascending order by $sentiment_score
ktc.df.3.sorted <- ktc.df.3 %>%
select(comments, sentiment_score) %>%
arrange(sentiment_score)| comments | sentiment_score |
|---|---|
| I haven’t used the ball machine therefore for Q3 it was difficult to rate my experience | -0.5 |
| We are in desperate need of a new ball machine. If we had a reliable modern machine then people would use it and develop their game, especially the lower ranked players. Please invest in this now | -0.13 |
| I feel there is other priorities within the club that we should be looking to improve rather than spending money on a ball machine that will only be used by a few members. | -0.11 |
| New ball machine may only be used by a small minority. | -0.04 |
| I would definitely use a ball machine if I thought it would be reliable | 0 |
| Battery life not long enough. | 0.01 |
| It desperately needs replaced. I’d be down practising more if it was a better set up with the machine. | 0.06 |
| The ball machine is only useful for drilling at a push. In a match you don’t face the same ball twice and a ball machine simply does not give you that. It’s better to just have hitting partners. The club in my opinion should not be spending a large amount of money. I’m a coach and even for feeding I don’t use it as it often doesn’t give my players the exact shot that I want to work with them. A very small percentage of the club actually use it and to me a ball machine is a waste of time. | 0.07 |
| I had been using the current ball on a regular basis but stopped because it was so unreliable. Attempts have been made to improve it but it isn’t fully functional because it’s old. I would LOVE to have a new machine. It would really help my game and I would use it often. I think the club needs to have a new and reliable ball machine. | 0.08 |
| The current one runs out of battery too quickly - we need a new one | 0.16 |
| No explanation has been given that we are looking to upgrade the ball machine. The purpose of this survey should be to ascertain who will be interested in using a ball machine if we upgrade our existing one regardless of whether you represent KTC in the leagues or not. | 0.25 |
| Would be more likely to use a more modern ball machine | 0.3 |
| I would love the club to get a new, reliable ball machine. | 0.32 |
| The ball machine is a great tool but it’s at the point where it’s not really serving that purpose any more. It’s used by quite a lot of members - and I’m sure more would use it if it was known to be reliable and useful. | 0.42 |
# Create a basic treemap using $features. Relative priority given by position in list (first=most important). List separator is ';'
library(treemap)
# Split features into individual rows
features_list <- strsplit(ktc.df.2$features, ";")
# Create a list of features and their weights
feature_weight_pairs <- lapply(features_list, function(x) {
len <- length(x)
data.frame(
feature = trimws(x),
weight = rev(seq_len(len)) # Assign inverse position weights
)
})
# Combine into a single data frame
features_df <- do.call(rbind, feature_weight_pairs)
# Remove empty strings
features_df <- features_df %>% filter(feature != "")
# Aggregate to get total weight for each feature
features_agg <- features_df %>%
group_by(feature) %>%
summarise(total_weight = sum(weight), .groups = 'drop') %>%
arrange(desc(total_weight))
# Create treemap
treemap(features_agg,
index = "feature",
vSize = "total_weight",
title = "Members' priorities for new ball machine features",
palette = "Set3",
border.col = "white")Footnotes
One response from coaches’ survey and one, identified as a coach’s response, from general survey. FOr this report that coach that provided information in members’ survey is treated as a member rather than a coach in order to respect the format they chose.↩︎