Я пытаюсь измерить политическую идеологию в Твиттере (используя Rtweet). Теперь у меня есть фрейм данных, состоящий из +100 политиков user_id вместе с двумя идеальными баллами по «фактору 1» и «фактору 2» (оба фактора имеют диапазон от 1 до 4). Выглядит это так (называется кандидат):
Затем я хотел бы определить, подписаны ли случайные пользователи Twitter на одного или нескольких политиков из моего набора данных. Если они, например. следуйте за двумя политиками в моем наборе данных — «Politician1» и «Politician2» — затем я назначу пользователю среднее значение идеальных очков двух политиков по двум факторам. Примером пользователя Twitter, следящего за этими двумя политиками, может быть фактор 1 = (3,5+1,0)/2 = 2,25 и фактор 2 = (2,0+4,0)/2 = 3,00.
Поэтому я попытался создать упрощенную петлю, включающую только двух журналистов из Твиттера, называемых «пользователями-испытателями», которые оба следят за большей частью политиков в моем наборе данных. Затем цикл должен проверить, следуют ли соответствующие журналисты одному или нескольким политикам: если они следуют, то цикл должен присвоить среднее значение значений, как описано выше. В противном случае они должны быть автоматически удалены из набора данных. Цикл ниже выполняется, но, к сожалению, выдает неверный результат (см. таблицу под кодом):
### loop ###
for(i in 1:ncol(testusers)){
#pick politician1 of dataset
politician1_friends <- get_friends(testusers$Navne[1])
#intersect with candidate data
ids_intersect = intersect(politician1_friends$user_id, kandidat$user_id)
if (length(ids_intersect == 0)){
testusers[i, "anyFriends"] <- FALSE #user has no friends in the politicians df
} else {
#assign values to user based on intersect
politicians_friends = kandidat[kandidat$user_id %in% ids_intersect,]
s1_mean <- mean(politicians_friends$faktor1, na.rm=TRUE)
s2_mean <- mean(politicians_friends$faktor2, na.rm=TRUE)
testusers[i, "faktor1"] <- s1_mean
testusers[i, "faktor2"] <- s2_mean
testusers[i, "anyFriends"] <- TRUE #user has friends in the politicians dataset
}
# etc.
}
Приведенный выше код дает мне этот вывод:
Состав тестировщиков: structure(list(Navne = c("Politician1", "Politician2"), anyFriends = c(FALSE, NA)), row.names = 1:2, class = "data.frame")
. И я не могу опубликовать всю структуру кандидата, так как он слишком большой: но это фрейм данных, состоящий из политик (со всей информацией из функции look_up()
, такой как user_id, screen_name, текст и т.
Поэтому я предполагаю, что код нуждается в незначительных изменениях, но я еще не понял их. В идеале вывод (df) должен состоять из «всего» трех столбцов фрейма данных: 1) UserID/Name 2) Faktor1 3) Faktor2?
Я думаю, вам нужен еще один data.frame
или около того, содержащий ваших пользователей и их «баллы». R предпочитает работать с такими фреймами данных, а не со списками.
Теперь я предполагаю, что у вас есть data.frame
, содержащий ваших политиков и т. д. и их оценки по двум измерениям, а также data.frame
с интересующими вас пользователями, например
kandidat <- data.frame(user_id = 1:2, name = c("Politician1", "Politican2"), Faktor1 = c(3.5, 2), Faktor2 = c(1,4))
my_users <- data.frame(name = c("Max", "Mara"))
Теперь, если вы хотите работать с циклом for, вы можете сделать что-то вроде
find_f <- function(df){
F1_mean <- c()
F2_mean <- c()
anyFriends <- c()
for(i in 1:nrow(df)){
#pick user1 of dataset
user_friends <- get_friends(df$name[i])
#intersect with our candidatedata
ids_intersect = intersect(user_friends$user_id, politicians$user_id)
if (length(ids_intersect)==0){
anyFriends <- c(anyFriends, FALSE) # User has no friends in the politicians df
} else {
#assign values to user based on intersect - don't know what to do here
kandidat_friends = kandidat[kandidat$user_id %in% ids_intersect,]
F1_mean <- c(F1_mean, mean(kandidat_friends$Faktor1, na.rm=TRUE))
F2_mean <- c(F2_mean, mean(kandidat_friends$Faktor2, na.rm=TRUE))
anyFriends <- c(anyFriends, TRUE) # user has friends in the politicans dataset
}
}
df$Faktor1 <- F1_mean
df$Faktor2 <- F2_mean
df$anyFriends <- anyFriends
return(df[df$anyFriends,])
}
my_users2 <- find_f(my_users)
Это далеко не очень краткое решение, но я думаю, что его легко понять. Самое главное, что вы работаете с data.frames, а не со списками, в R это намного проще. В каждой итерации мы получаем друзей пользователя, смотрим, нет ли пересечения с политиками. Если нет, мы присваиваем логическое значение FALSE
переменной anyFriends
в фрейме данных my_users
, чтобы мы могли легко отфильтровать их в конце. Если есть пересечение, мы берем среднее значение двух оценок выбранных политиков и назначаем их соответствующей записи пользователя.
На мой взгляд, нет необходимости в списке IDEOLOGISCORE. Кроме того, имейте в виду, что я не тестировал приведенный выше код, и, возможно, в нем есть опечатки. Просто проверьте, работает ли это для вас :)
Не могли бы вы предоставить воспроизводимый пример
Любой, кто комментирует это, должен знать структуру testusers
и kandidat
. Например, используйте dput(testusers[1:5,])
для создания вывода, с которым может работать любой.
Структуры testusers
и kandidat
теперь добавляются к исходному вопросу вместе с упрощением. К сожалению, цикл по-прежнему не присваивает значения правильно.
Я отредактировал свой пост с решением, которое должно работать (я протестировал его на примере user_friends
dataframe, но, поскольку я не знаю, как именно user_friends
выглядит для вас, я не могу сказать наверняка.
Петля теперь работает как положено при использовании только двух человек! Однако, когда я беру случайную выборку, например. 250 человек и пытаюсь запустить цикл, я немедленно превышаю ограничение сети get_friends на 15 человек («Предупреждение: превышен предел скорости — 88»). Итак, я думаю, что последний шаг — включить какую-то функцию retryonratelimit = TRUE или Sys.sleep()? Я думаю, что это должно быть либо продолжением команды the user_friends <- get_friends(df$name[i])
, либо my_users2 <- find_f(my_users)
, но я вообще не могу заставить ее работать. Код для моего цикла идентичен тому, который опубликовал @Ben.
ПРИМЕЧАНИЕ. При выполнении команды my_users2 <- find_f(my_users)
внизу появляется сообщение («Предупреждение: превышен предел скорости — 88»).
Вам следует подумать о том, чтобы прочитать try
/ tryCatch
в этом отношении, чтобы поймать ошибку, выдаваемую Twitter API относительно ограничения скорости. В случае ошибки вы можете вызвать 15-минутный сон или что-то в этом роде. Но это другая тема.
А sys.sleep (60*15) внизу цикла? Или при запуске my_users2 <- find_f(my_users)
после этого?
Ваш цикл
for
нигде не использует индексi
.