Выберите строку по уровню фактора

Моя проблема связана с тем, что я уже определил строки, которые я хочу выбрать по уровню фактора, используя другой код. В основном то, что у меня есть:

df<-data.frame(ID=c("A","B","C"), pos=c(1,3,2))
df2<-data.frame(ID=c(rep("A",5),rep("B",5),rep("C",5)),obs=c(1:15))

В df pos соответствует индексу строки, но в пределах одного уровня идентификатора, а не во всей области данных df2. Поэтому я ищу способ выбора строк для каждого идентификатора в соответствии с правильным индексом (поэтому их число строк в пределах уровня каждого коэффициента df2).

Это дало бы мне:

df3<-data.frame(ID=c("A","B","C"), obs=c(1,8,12))

Ответ 1

Здесь основное решение R:

df2$pos <- ave(df2$obs, df2$ID, FUN=seq_along)
merge(df, df2)
  ID pos obs
1  A   1   1
2  B   3   8
3  C   2  12

Если df2 сортируется по ID, вы можете просто сделать df2$pos <- sequence(table(df2$ID)) для первой строки.

Ответ 2

dplyr

library(dplyr)

merge(df,df2) %>% 
  group_by(ID) %>% 
  filter(row_number() == pos) %>%
  select(-pos)

#   ID obs
# 1  A   1
# 2  B   8
# 3  C  12

база R

df2m <- merge(df,df2)
do.call(rbind, 
  by(df2m, df2m$ID, function(SD) SD[SD$pos[1], setdiff(names(SD),"pos")]) 
)

by разделяет объединенный фрейм данных df2m на df2m$ID и работает с каждой частью; он возвращает результаты в списке, поэтому они должны быть rbind ed вместе в конце. Каждое подмножество данных (связанных с каждым значением ID) фильтруется с помощью pos и отменяет выбор столбца "pos", используя обычный синтаксис data.frame.

data.table, предложенный @DavidArenburg в комментарии

library(data.table)

setkey(setDT(df2),"ID")[df][, 
  .SD[pos[1L], !"pos", with=FALSE]
, by = ID]

Первая часть - setkey(setDT(df2),"ID")[df] - это слияние. После этого результирующая таблица разбивается на by = ID, и каждый подмножество данных .SD работает. pos[1L] является подмножеством нормальным образом, а !"pos", with=FALSE соответствует отбрасыванию столбца pos.

См. ответ @eddi для лучшего подхода к таблице данных.

Ответ 3

Использование data.table версия 1.9.5 +:

setDT(df2)[df, .SD[pos], by = .EACHI, on = 'ID']

который сливается в столбце ID, затем выбирает строку pos для каждой из строк df.