小填字游戏。和往常一样,我认为我缺少了一些东西。我有一个这样的数据框:
id creator att1 att2 att3 att... att500
a1 person1 TRUE TRUE FALSE ...
a2 person2 TRUE TRUE TRUE ...
a3 person1 TRUE FALSE FALSE ...
a4 person1 TRUE TRUE FALSE ...
a5 person2 TRUE TRUE FALSE ...
以此类推。我想计算不同创建者的相同属性组合(大约500个布尔值)的出现次数,并针对每一行执行此操作,将计数添加到相应的行中。因此,在上面的示例中,我希望第一行(a1)的count = 1,因为在a5中,其他人执行了非常相同的属性组合。请注意,a4不计算在内,因为它是相同的组合,但是是同一个人的。想一想自己混合的鸡尾酒,以及不同人彼此独立地混合鸡尾酒的频率。行a2的计数应为0,由于a5,a3(没有相同的属性组合)和a4的计数应分别为1。 a5的计数也为1。但是,如果其他人多次混合同一鸡尾酒,则应计算在内。我不想简单地删除重复项。
因此,我的计划是遍历各行,排除该行的同一创建者的所有鸡尾酒,采用属性组合并将其与临时数据集中的所有行进行比较:
for (row in 1:nrow(data)){
# for each row in data
creator <- row$creator
# get creator
attr_tupel <- row[1, 3:500]
#return the attribute combination of the row
data[row]$count <- nrow(data[data$creator != creator & data[3:500] == attr_tupel])
# into the column $count of the current row write the number of observations that are not from the same creator and match the exact tupel of my ~500 Attributes (equal cocktails by different persons)
}
不幸的是,我无法将参考行的手风琴与其他行的手风琴进行比较,因为 “ ==”仅适用于大小相等的数据帧
现在我被卡住了。我肯定可以分别写每一列-但是要花一些时间。我是否需要将该数据帧转换为列表或向量或 //在此处插入sthg // (向量和列表无效)。是否可以将一行值与多个值进行比较?其他行是否平等?我不认为有重复的行是解决方案,除了通常R会在没有任何可比较的条件时简单地遍历条目。为什么不在这里?
我阅读了一些有关相互比较几列的主题,但是并没有成功地将解决方案转移到我的问题上。例如:wants to look up one value for the boolish value, I have multiple TRUE values , same,wants to convert to a c() - which I could do too and compare those, but kind of a hard way, isn't it?
最后(从最后一个链接开始),我现在甚至考虑将布尔值转换为数字(添加索引,以便我们拥有
id creator att1 ... index
a1 person1 1 2 0 ... 3
a2 person2 1 2 3 ... 6
并比较该索引。应该管用。但是那种感觉是一个丑陋的解决方法。同样,当考虑使用布尔值以外的数据(例如几个字符串)时,从长远来看,我仍然希望能够将一列列数据相互比较,而与它们的内容无关。
我想念什么? :)
感谢您的帮助!
如注释中所要求的,这里是创建类似数据框的简短脚本。请记住,尽管还有更多列可以比较。
id <- 1:50
names <- paste("creator", rep(1:10, each = 5))
bools1 <- rnorm(n=50, mean = 5, sd = 3)
bools1 <- ifelse(bools1>5, TRUE, FALSE)
bools2 <- rnorm(n=50, mean = 5, sd = 3)
bools2 <- ifelse(bools2>5, TRUE, FALSE)
bools3 <- rnorm(n=50, mean = 5, sd = 3)
bools3 <- ifelse(bools3>5, TRUE, FALSE)
bools4 <- rnorm(n=50, mean = 5, sd = 3)
bools4 <- ifelse(bools4>5, TRUE, FALSE)
bools5 <- rnorm(n=50, mean = 5, sd = 3)
bools5 <- ifelse(bools5>5, TRUE, FALSE)
data <- data.frame(id, names, bools1, bools2, bools3, bools4, bools5)
答案 0 :(得分:1)
编辑:抱歉-我的第一个解决方案误解了问题。试试这个
您可以使用数据表来运行它:
#Your set up data (with seed)
set.seed(123)
id <- 1:50
names <- paste("creator", rep(1:10, each = 5))
bools1 <- rnorm(n=50, mean = 5, sd = 3)
bools1 <- ifelse(bools1>5, TRUE, FALSE)
bools2 <- rnorm(n=50, mean = 5, sd = 3)
bools2 <- ifelse(bools2>5, TRUE, FALSE)
bools3 <- rnorm(n=50, mean = 5, sd = 3)
bools3 <- ifelse(bools3>5, TRUE, FALSE)
bools4 <- rnorm(n=50, mean = 5, sd = 3)
bools4 <- ifelse(bools4>5, TRUE, FALSE)
bools5 <- rnorm(n=50, mean = 5, sd = 3)
bools5 <- ifelse(bools5>5, TRUE, FALSE)
data <- data.frame(id, names, bools1, bools2, bools3, bools4, bools5)
# Code to run
library(data.table)
setDT(data)
dt_m <- melt(data, id.vars = c("id","names"), variable.factor = TRUE)
dt_m <- dt_m[,.(drink = paste0(value, collapse = "_")), by = .(id, names)]
dt_m[, times_made := .N, by = drink][, times_made_others := times_made - .N, by = .(drink, names)]
dt_out <- merge(data, dt_m[, .(id, drink, times_made_others)], by = "id")
基本上,您正在做的是通过将各列折叠在一起,计算其他人饮用饮料的次数,然后将其合并回原始数据集来创建“饮料”。
dt_out
id names bools1 bools2 bools3 bools4 bools5 drink times_made_others
1: 1 creator 1 FALSE TRUE FALSE TRUE TRUE FALSE_TRUE_FALSE_TRUE_TRUE 3
2: 2 creator 1 FALSE FALSE TRUE TRUE TRUE FALSE_FALSE_TRUE_TRUE_TRUE 1
3: 3 creator 1 TRUE FALSE FALSE TRUE FALSE TRUE_FALSE_FALSE_TRUE_FALSE 2
4: 4 creator 1 TRUE TRUE FALSE FALSE TRUE TRUE_TRUE_FALSE_FALSE_TRUE 0
5: 5 creator 1 TRUE FALSE FALSE FALSE FALSE TRUE_FALSE_FALSE_FALSE_FALSE 3
6: 6 creator 2 TRUE TRUE FALSE FALSE FALSE TRUE_TRUE_FALSE_FALSE_FALSE 2
7: 7 creator 2 TRUE FALSE FALSE TRUE FALSE TRUE_FALSE_FALSE_TRUE_FALSE 2