Я попросил участников написать три слова и присвоить каждому слову номер. Некоторые слова написали несколько участников, другие — только один участник. Теперь я пытаюсь создать набор переменных, по одной для каждого слова, упомянутого участниками, содержащих значение, которое каждый участник присвоил этому слову (если он/она написал это слово). Я написал функцию для этого, но она не дает ожидаемого результата. Я предполагаю, что это связано с неправильной интерпретацией в функции всех слов моего вектора символов.
Я создал следующий образец даты, чтобы проиллюстрировать проблему.
data <- data.frame(
words1 = c("apple", "pear", "banana", "pear", "banana"),
words2 = c("pear", "banana", "pear", "banana", "cherry"),
words3 = c("banana", "ananas", "apple", "melon", "pear"),
value1 = c(2, 1, 2, 0, 1),
value2 = c(2, 0, 0, 2, 0),
value3 = c(0, 2, 2, 1, 1)
)
allwords <- c("apple", "pear", "banana", "ananas", "melon", "cherry")
attach(data)
head(data)
words1 words2 words3 value1 value2 value3
1 apple pear banana 2 2 0
2 pear banana ananas 1 0 2
3 banana pear apple 2 0 2
4 pear banana melon 0 2 1
5 banana cherry pear 1 0 1
Я хочу создать набор векторов, каждый из которых посвящен одному из слов во всех словах, сообщая значение, которое каждый участник присвоил этому слову (NA, если значение не назначено). Это результат, который я пытаюсь получить:
apple pear banana ananas melon cherry
2 2 0 NA NA NA
NA 1 0 2 NA NA
2 0 2 NA NA NA
NA 0 2 NA 1 NA
NA 1 1 NA NA 0
Я написал эту функцию для достижения этой цели
value.f <- function(y){
values.w[[y]] <- NA
value.var <- values.w[[y]]
value.var[which(data$words1 == y)] <- data$value1
value.var[which(data$words2 == y)] <- data$value2
value.var[which(data$words3 == y)] <- data$value3
}
values.w <- list()
values.w <- lapply(allwords, value.f)
names(values.w) <- c(allwords)
Но для каждого слова я получаю содержимое data$value3. В принципе все "какие" условия признаны верными, но я не понимаю почему.
as.data.frame(values.w)
apple pear banana ananas melon cherry
0 0 0 0 0 0
2 2 2 2 2 2
2 2 2 2 2 2
1 1 1 1 1 1
1 1 1 1 1 1
Я не понимаю, что делаю не так, но мне очень трудно использовать векторы символов в функциях lapply()
, поэтому я предполагаю, что у меня возникла такая проблема.
Я пробовал с eval(parse(text=y)
, пробовал с paste0(y)
, но ничего из этого не работает.
names(data)
предполагает, что имена data.frame не такие, как вы ожидаете. Замените назначение <-
, используемое при построении фрейма данных, на =
, например. г. words1 = ...
вместо words1 <- ...
и ваш код должен работать.
@I_O Спасибо, это была небольшая ошибка с моей стороны. Я исправил это в вопросе. Конечно, это не имеет ничего общего с функцией, которая все еще не дает ожидаемого результата.
@Friede К сожалению, это не имеет ничего общего с заменой 0 на NA. Я пытаюсь создать новые столбцы, по одному для каждого слова. Я попытался объяснить проблему лучше в своем вопросе.
@Сильвия: Я добавила рабочую версию вашей первоначальной попытки в конце своего ответа. Проблемы были не с векторами символов или lapply
.
Одна возможность. Он использует {dplyr}, у которого есть функция bind_rows
, которая может связывать строки данных с различным составом переменных, не жалуясь на то, что переменные не совпадают (как это было бы rbind
).
## words1 words2 words3 value1 value2 value3
## 1 apple pear banana 2 2 0
## 2 pear banana ananas 1 0 2
## 3 banana pear apple 2 0 2
## 4 pear banana melon 0 2 1
## 5 banana cherry pear 1 0 1
itemcount
элементы как имена (столбцов), а вторые itemcount
элементы как значения: row_to_named_list <- \(row, itemcount = 3){
setNames(row[1:itemcount + itemcount],
row[1:itemcount]
)
}
do.call
для вызова функции (bind_rows
) в списке (однострочных фреймов данных, возвращаемых lapply
вышеуказанной вспомогательной функцией с индексами строк 1:5): library(dplyr)
do.call(dplyr::bind_rows,
lapply(1:5, \(r) row_to_named_list(data[r, ]))
)
выход:
## apple pear banana ananas melon cherry
## 1 2 2 0 NA NA NA
## 2 NA 1 0 2 NA NA
## 3 2 0 2 NA NA NA
## 4 NA 0 2 NA 1 NA
## 5 NA 1 1 NA NA 0
редактировать
Ниже приведена адаптированная версия вашей функции, которая работает должным образом. Основными ошибками были невозможность вернуть результат функции и перезапись value.var
в неправильных позициях, value3
переопределяя предыдущие замены.
value.f <- function(y){
## `<-` can't change objects outside the function from within
## the function anyway:
## values.w[[y]] <- NA
## this would create a single-item value.var containing only NA
## value.var <- values.w[[y]]
value.var <- rep(NA, 5) ## instantiate value.var as an NA-vector of desired length
## replacement values must have same length as replacement positions:
value.var[which(data$words1 == y)] <- data$value1[which(data$words1 == y)]
value.var[which(data$words2 == y)] <- data$value2[which(data$words2 == y)]
value.var[which(data$words3 == y)] <- data$value3[which(data$words3 == y)]
## don't forget to return value.var!
value.var
}
## values.w <- list() # lapply returns a list anyway
values.w <- lapply(allwords, value.f2)
names(values.w) <- c(allwords)
list2DF(values.w) ## make this a dataframe
Спасибо и за объяснение!
Это выглядит как типичная задача, для которой вам следует использовать соединение. Однако я не понимаю порядок ожидаемого результата. Вы как будто теряете отношение к участникам.
library(data.table)
setDT(data)
#create index column
data[, id := .I]
#transform to long format
DT <- melt(data, measure.vars = patterns(word = "^word", value = "^value"))
#join
DT <- DT[#all possible combinations of ids and words:
CJ(word = allwords, id = unique(DT[["id"]])),
#which columns to join on:
on = c("word", "id")]
#transform to wide format
dcast(DT, id ~ word, value.var = "value")
# Key: <id>
# id ananas apple banana cherry melon pear
# <int> <num> <num> <num> <num> <num> <num>
# 1: 1 NA 2 0 NA NA 2
# 2: 2 2 NA 0 NA NA 1
# 3: 3 NA 2 2 NA NA 0
# 4: 4 NA NA 2 NA 1 0
# 5: 5 NA NA 1 0 NA 1
В ожидаемом результате было несколько опечаток, спасибо, что заметили их!
@Silvia Я не думаю, что это опечатки, но порядок столбцов отличается от ожидаемого результата в вопросе.
Я не понимаю. Просто заменить
0
наNA
?