Как заменить значения в фрейме данных строкой в ​​R?

короткая версия: как заменить значения в фрейме данных строкой, найденной в другом фрейме данных?

более длинная версия: я биолог, работающий со многими видами пчел. У меня есть набор данных со многими тысячами пчел. Каждая строка имеет уникальный идентификатор пчелы # вместе со всей соответствующей информацией об этом образце (данные об отлове, местоположение GPS и т. д.). Информация о виде для каждой пчелы не была введена, потому что их идентификация занимает много времени. При идентификации я получаю ящики с сотнями пчел одного вида. Я ввожу их в отдельный фрейм данных. Я пытаюсь написать код, который будет обновлять исходный файл данных информацией о видах (семейство, род, виды, пол и т. д.), когда я идентифицирую пчел. В настоящее время в исходном файле данных информация о видах пуста и интерпретируется как NA в R. Я хочу, чтобы R нашел все уникальные идентификаторы пчел и заполнил информацию о видах, но мне трудно понять, как это сделать. замените значения NA строкой (например, «Andrenidae»)

Вот простой пример того, что я пытаюсь сделать:

rawData<-data.frame(beeID=c(1:20),family=rep(NA,20))
speciesInfo<-data.frame(beeID=seq(1,20,3),family=rep("Andrenidae",7))

rawData[rawData$beeID == 4,"family"]  <- speciesInfo[speciesInfo$beeID == 4,"family"]

Итак, я заменяю вещи, как хочу, но номером, а не фамилией (строкой). В конечном итоге я хотел бы написать небольшой цикл, чтобы добавить всю информацию о видах, например:

for (i in speciesInfo$beeID){
  rawData[rawData$beeID == i,"family"]  <- speciesInfo[speciesInfo$beeID == i,"family"]
}

Заранее благодарю за любой совет!

Ваше здоровье,

Зак

РЕДАКТИРОВАТЬ:

Я только что заметил, что первые два метода ниже каждый раз добавляют новый столбец, что вызвало бы проблемы, если бы мне нужно было добавлять информацию о видах несколько раз (что я обычно и делаю). Например:

rawData<-data.frame(beeID=c(1:20),family=rep(NA,20))
Andrenidae<-data.frame(beeID=seq(1,20,3),family=rep("Andrenidae",7))
Halictidae<-data.frame(beeID=seq(1,20,3)+1,family=rep("Halictidae",7))

# using join
library(plyr)
rawData <- join(rawData, Andrenidae, by = "beeID", type = "left")
rawData <- join(rawData, Halictidae, by = "beeID", type = "left")

# using merge
rawData <- merge(x=rawData,y=Andrenidae,by='beeID',all.x=T,all.y=F)
rawData <- merge(x=rawData,y=Halictidae,by='beeID',all.x=T,all.y=F)

Есть ли способ свернуть столбцы, чтобы у меня был один единый фрейм данных? Или способ обновить rawData, а не добавлять каждый раз новый столбец? Заранее спасибо!


person Arturito    schedule 11.09.2012    source источник


Ответы (4)


Вот функция, я думаю, будет работать для вас. Это использует match для поиска и индексирования значений в вашем фрейме данных аннотации, а затем заменяет значения в rawData.

replaceID <- function(to,from,mergeBy,values){
  x <- match(from[,mergeBy],to[,mergeBy])
  to[,values][x] <- as.character(from[,values])
  return(to)
}
> rawData <- replaceID(rawData,Halictidae,"beeID","family")
> rawData
   beeID     family
1      1       <NA>
2      2 Halictidae
3      3       <NA>
4      4       <NA>
5      5 Halictidae
6      6       <NA>
7      7       <NA>
8      8 Halictidae
9      9       <NA>
10    10       <NA>
11    11 Halictidae
12    12       <NA>
13    13       <NA>
14    14 Halictidae
15    15       <NA>
16    16       <NA>
17    17 Halictidae
18    18       <NA>
19    19       <NA>
20    20 Halictidae
person Matt Shirley    schedule 11.09.2012
comment
Это идеально, он делает именно то, что я изначально предполагал. Спасибо вам за помощь! Привет, Зак - person Arturito; 12.09.2012

Другой вариант — использовать ?join в пакете plyr.

    library(plyr)
#Adding family ahead of time was unnecessary so I'll remove it alongside the join.
join(rawData, speciesInfo, by = "beeID", type = "left")[,-2]
   beeID     family
1      1 Andrenidae
2      2       <NA>
3      3       <NA>
4      4 Andrenidae
5      5       <NA>
6      6       <NA>
7      7 Andrenidae
8      8       <NA>
9      9       <NA>
10    10 Andrenidae
11    11       <NA>
12    12       <NA>
13    13 Andrenidae
14    14       <NA>
15    15       <NA>
16    16 Andrenidae
17    17       <NA>
18    18       <NA>
19    19 Andrenidae
20    20       <NA>

Обновлять

# If you anticipate adding new species over time, 
# simply rbind those into a single reference data.frame to merge with your rawData. 
# Like so:
library(plyr)
rawData <- join(rawData, rbind(Andrenidae, Halictidae), by = "beeID", type = "left")

# To keep you code clean, you could do this step ahead of time
species_list <- rbind(Andrenidae, Halictidae)
rawData <- join(rawData, species_list, by = "beeID", type = "left")
person Maiasaura    schedule 11.09.2012
comment
Я не знал, как включить код в ответ, поэтому отредактировал исходный вопрос, добавив дополнительный вопрос. Я всегда был скрытником, поэтому мне еще предстоит научиться вносить свой вклад. Еще раз спасибо за любую помощь! - person Arturito; 11.09.2012
comment
Рад, что вы отредактировали свой вопрос (именно так должен работать SO, т. Е. Уточнить и улучшить свой вопрос на основе ответов). Отредактированный ответ должен относиться к вашему новому вопросу. Если ваш набор данных становится значительно больше, для этого есть более мощные решения. - person Maiasaura; 11.09.2012

Вы можете использовать функцию слияния, например :

rawData <- data.frame(beeID=c(1:20),family=rep(NA,20))
speciesInfo <- data.frame(beeID=seq(1,20,3),
                          family=c(rep('Halictidae',4), rep("Andrenidae",3)))

merged <- merge(x=rawData,y=speciesInfo,by='beeID',all.x=T,all.y=F)
merged$family.x <- NULL # remove the family.x column
names(merged) <- c('beeID','family') # rename the columns

Примечание

Нет необходимости инициализировать rawData столбцом family.
Функция слияния добавит его автоматически, например. :

rawData <- data.frame(beeID=c(1:20))
speciesInfo <- data.frame(beeID=seq(1,20,3),
                          family=c(rep('Halictidae',4), rep("Andrenidae",3)))

merged <- merge(x=rawData,y=speciesInfo,by='beeID',all.x=T,all.y=F)

> merged
   beeID     family
1      1 Halictidae
2      2       <NA>
3      3       <NA>
4      4 Halictidae
5      5       <NA>
6      6       <NA>
7      7 Halictidae
8      8       <NA>
9      9       <NA>
10    10 Halictidae
11    11       <NA>
12    12       <NA>
13    13 Andrenidae
14    14       <NA>
15    15       <NA>
16    16 Andrenidae
17    17       <NA>
18    18       <NA>
19    19 Andrenidae
20    20       <NA>
person digEmAll    schedule 11.09.2012

Решение data.table, которое будет эффективно использовать память и время.

  • Обратите внимание, что вам нужно иметь stringsAsFactors = F для rbindlist (сверхбыстрая версия do.call(rbind,list) / rbind)
  • Я добавил еще один столбец в качестве фиктивных данных к объекту rawData и удалил семейство.

Создайте данные -

rawData <- data.frame(beeID = c(1:20), other_stuff = sample(letters, 20), stringsAsFactors = F)
Andrenidae <- data.frame(beeID = seq(1, 20, 3), family = rep("Andrenidae", 7), stringsAsFactors = F)
Halictidae <- data.frame(beeID = seq(1, 20 , 3)+  1, family = rep("Halictidae", 7), stringsAsFactors = F)
library(data.table)
# convert to data.table
rawDT <- as.data.table(rawData)
# combine the list of Species-specific data.frames into a large data.table
speciesInfo <- rbindlist(list(Andrenidae, Halictidae))
# set the keys, to allow efficient use of data.table and its merging 
# abilities. The keys are the same for both 
setkeyv(rawDT, 'beeID')
setkeyv(speciesInfo, 'beeID')
# merge by key 
speciesInfo[rawDT, nomatch = NA]
## beeID     family other_stuff
## 1:     1 Andrenidae           s
## 2:     2 Halictidae           x
## 3:     3         NA           i
## 4:     4 Andrenidae           e
## 5:     5 Halictidae           v
## 6:     6         NA           q
## 7:     7 Andrenidae           w
## 8:     8 Halictidae           c
## 9:     9         NA           u
## 10:    10 Andrenidae           z
## 11:    11 Halictidae           y
## 12:    12         NA           a
## 13:    13 Andrenidae           l
## 14:    14 Halictidae           r
## 15:    15         NA           h
## 16:    16 Andrenidae           o
## 17:    17 Halictidae           n
## 18:    18         NA           g
## 19:    19 Andrenidae           p
## 20:    20 Halictidae           m

or

rawDT[speciesInfo]

##    beeID other_stuff     family
## 1:     1           s Andrenidae
## 2:     2           x Halictidae
## 3:     4           e Andrenidae
## 4:     5           v Halictidae
## 5:     7           w Andrenidae
## 6:     8           c Halictidae
## 7:    10           z Andrenidae
## 8:    11           y Halictidae
## 9:    13           l Andrenidae
## 10:   14           r Halictidae
## 11:   16           o Andrenidae
## 12:   17           n Halictidae
## 13:   19           p Andrenidae
## 14:   20           m Halictidae

Какие данные вас интересуют

person mnel    schedule 12.09.2012