0

次の問題に対するベクトル化された解決策を考え出すのに苦労しています。私は2つのデータフレームを持っています:

> people <- data.frame(name = c('Fred', 'Bob'), profession = c('Builder', 'Baker'))
> people
  name profession
1 Fred    Builder
2  Bob      Baker

> allowed <- data.frame(name = c('Fred', 'Fred', 'Bob', 'Bob'), profession = c('Builder', 'Baker', 'Barman', 'Biker'))
> allowed
  name profession
1 Fred    Builder
2 Fred      Baker
3  Bob     Barman
4  Bob     Biker

つまり、すべての人が許可された職業を持っているかどうかを確認し、許可されていない名前を返したいのです。

たとえば、フレッドはビルダーにもパン屋にもなれるので、問題ありません。ただし、Bob は Barman または Biker になることができますが、Baker になることはできません (注: 私の使用例では許可されている職業は 2 つだけです)。

許可された職業を持たない名前のデータ フレームを返したい:

name profession permitted
1 Bob Baker Biker
2 Bob Baker Barman

助けてくれてありがとう

4

4 に答える 4

1

シンプルなベースのみのソリューション。誰かがもっと良いものを思いつくことができると確信しています。

out <- allowed[!allowed$name %in% merge(people, allowed)$name, ]

これにより、許可された職業とともに、希望する人々が得られます。彼らの実際の職業も知りたい場合:

names(out)[2] <- "permitted"
out <- merge(people, out, all.y=TRUE)
于 2013-06-13T11:03:22.993 に答える
1

これは、もう少し読みやすいdata.tableソリューションです。読みやすいと思われる場合は、同じ行で最後のステップを実行してワンライナーにすることもできます。

# load library, convert people to a data.table and set a key
library(data.table)
people = data.table(people, key = "name,profession")

# compute
result = data.table(allowed, key = "name")[people[!allowed]]
setnames(result, "profession.1", "permitted")

result
#   name profession permitted
#1:  Bob     Barman     Baker
#2:  Bob      Biker     Baker
于 2013-06-13T15:01:40.043 に答える
0

おそらく別の方法がありますが、これでうまくいくはずです。データセット全体に関数を適用する方法を示すために、許可されていない職業の第三者を追加しました。

currentprof <-structure(list(name = structure(c(2L, 1L, 3L), .Label = c("Bob", 
"Fred", "Jan"), class = "factor"), profession = structure(c(3L, 
2L, 1L), .Label = c("Analyst", "Baker", "Builder"), class = "factor")), .Names = c("name", 
"profession"), class = "data.frame", row.names = c(NA, -3L))

allowed <- structure(list(name = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c("Bob", 
"Fred", "Jan"), class = "factor"), profession = structure(c(4L, 
1L, 2L, 3L, 6L, 5L), .Label = c("Baker", "Barman", "Biker", "Builder", 
"Driver", "Teacher"), class = "factor")), .Names = c("name", 
"profession"), class = "data.frame", row.names = c(NA, -6L))

checkprof <- function(name){
allowedn <- allowed[allowed$name == name,]
currentprofn <- currentprof[currentprof$name==name,]
if(!currentprofn$profession %in% allowedn$profession)
{result <- merge(currentprofn, allowedn, by = "name", all.x=TRUE)} else
{result <-data.frame(col1=character(),
                 col2=character(), 
                 col3=character(), 
                 stringsAsFactors=FALSE)}
colnames(result) <- c("name","profession","permitted")
return(result)
}


do.call(rbind,lapply(levels(allowed$name),checkprof))
于 2013-06-13T11:27:13.603 に答える
0

これが私の見解です。ただし、さらにテストが必要になる場合があります。私は自分で提案を受け入れます。あなたの例で動作しますが、一般化するかどうかはわかりません。

people$check <- ifelse(people$profession %in% allowed[which(allowed$name == people$name),"profession"], TRUE,FALSE)

people_select <- people[people$check == TRUE,]

編集:これが投票を妨げている場合の明確化のために。ifelse はベクトル化されており、非常に高速に実行されます。

于 2013-06-13T12:51:01.647 に答える