Я не уверен, что вы хотите достичь с помощью команды
topic_proportion_per_decade <- aggregate(theta, by = list(decade = tweets$decade), mean)
Насколько я вижу, вы производите только одно десятилетие с
tweets$decade <- paste0(substr(tweets$date2, 0, 3), "0")
table(tweets$decade)
2010
3481
Со всей предварительной обработкой от *От 1007 * до textdata
вы создаете несколько пустых строк.Это где ваша проблема начинается.Текстовые данные с новыми пустыми строками являются основой вашего corpus
и вашего dtm
.Вы избавляетесь от них с помощью строк:
ui = unique(dtm$i)
dtm.new = dtm[ui,]
В то же время вы в основном удаляете пустые столбцы в dtm, тем самым изменяя длину вашего объекта.Этот новый DTM без пустых ячеек является вашей новой основой для модели темы.Это будет беспокоить вас, когда вы попытаетесь использовать aggregate()
с двумя объектами разной длины: tweets$decade
, который по-прежнему имеет старую длину 3418 с theta
, созданную моделью темы, которая вПоворот основан на dtm.new - помните, тот, в котором меньше строк.
Я хотел бы сначала получить ID-столбец в tweets
.Позже вы можете использовать идентификаторы, чтобы выяснить, какие тексты впоследствии будут удалены вашей предварительной обработкой, и соответствовать длинам tweet$decade
и theta
.
Я переписал ваш код - попробуйте это:
library(readxl)
library(tm)
# Import text data
tweets <- read_xlsx("data.xlsx")
## Include ID for later
tweets$ID <- 1:nrow(tweets)
textdata <- tweets$text
#Load in the library 'stringr' so we can use the str_replace_all function.
library('stringr')
#Remove URL's
textdata <- str_replace_all(textdata, "https://t.co/[a-z,A-Z,0-9]*","")
textdata <- gsub("@\\w+", " ", textdata) # Remove user names (all proper names if you're wise!)
textdata <- iconv(textdata, to = "ASCII", sub = " ") # Convert to basic ASCII text to avoid silly characters
textdata <- gsub("#\\w+", " ", textdata)
textdata <- gsub("http.+ |http.+$", " ", textdata) # Remove links
textdata <- gsub("[[:punct:]]", " ", textdata) # Remove punctuation
#Change all the text to lower case
textdata <- tolower(textdata)
#Remove Stopwords. "SMART" is in reference to english stopwords from the SMART information retrieval system and stopwords from other European Languages.
textdata <- tm::removeWords(x = textdata, c(stopwords(kind = "SMART")))
textdata <- gsub(" +", " ", textdata) # General spaces (should just do all whitespaces no?)
# Convert to tm corpus and use its API for some additional fun
corpus <- Corpus(VectorSource(textdata)) # Create corpus object
#Make a Document Term Matrix
dtm <- DocumentTermMatrix(corpus)
ui = unique(dtm$i)
dtm.new = dtm[ui,]
#Fixes this error: "Each row of the input matrix needs to contain at least one non-zero entry" See: https://stackoverflow.com/questions/13944252/remove-empty-documents-from-documenttermmatrix-in-r-topicmodels
#rowTotals <- apply(datatm , 1, sum) #Find the sum of words in each Document
#dtm.new <- datatm[rowTotals> 0, ]
library("ldatuning")
library("topicmodels")
k <- 7
ldaTopics <- LDA(dtm.new, method = "Gibbs", control=list(alpha = 0.1, seed = 77), k = k)
#####################################################
#topics by year
tmResult <- posterior(ldaTopics)
tmResult
theta <- tmResult$topics
dim(theta)
library(ggplot2)
terms(ldaTopics, 7)
id <- data.frame(ID = dtm.new$dimnames$Docs)
colnames(id) <- "ID"
tweets$decade <- paste0(substr(tweets$date2, 0, 3), "0")
tweets_new <- merge(id, tweets, by.x="ID", by.y = "ID", all.x = T)
topic_proportion_per_decade <- aggregate(theta, by = list(decade = tweets_new$decade), mean)