gpt4 book ai didi

r - 基于多列组合 R 中的数据框行

转载 作者:行者123 更新时间:2023-12-02 07:27:46 25 4
gpt4 key购买 nike

我在 R 中有一个数据框,每行有一个个体。有时,个人会出现在两行中,我想根据重复的 ID 将这些行组合起来。

问题是,每个人都有多个ID,当一个ID出现两次时,它不一定出现在同一列

这是一个示例数据框:

dat <- data.frame(a = c('cat', 'canine', 'feline', 'dog'),
b = c('feline', 'puppy', 'meower', 'wolf'),
c = c('kitten', 'barker', 'kitty', 'canine'),
d = c('shorthair', 'collie', '', ''),
e = c(1, 5, 3, 8))

> dat
a b c d e
1 cat feline kitten shorthair 1
2 canine puppy barker collie 5
3 feline meower kitty 3
4 dog wolf canine 8

因此应合并第 1 行和第 3 行,因为第 1 行的 ID b 等于第 3 行的 ID a。同样,ID a第 2 行的 ID c 等于第 4 行的 ID c,因此这些行也应该合并。

理想情况下,输出应如下所示。

     a.1    b.1    c.1       d.1 e.1    a.2    b.3    c.2 d.2 e.2
1 cat feline kitten shorthair 1 feline meower kitty 3
2 canine puppy barker collie 5 dog wolf canine 8

(请注意,这些行不是根据空字符串的共享 ID 进行组合的。)

我对如何做到这一点的想法如下,但我很确定我走错了路,所以它们可能对解决问题没有帮助。

我认为我可以为每一行分配一个行ID,然后融化数据。之后,我可以逐行浏览。当我发现某一行的 ID 之一与较早的行匹配时(例如,当第 3 行 ID 之一与第 1 行 ID 之一匹配时),我将更改当前行的行 ID 的每个实例以匹配较早的行 ID (例如,所有行 ID 3 将更改为 1)。

这是我一直在使用的代码:

dat$row.id <- 1:nrow(dat)
library(reshape2)
dat.melt <- melt(dat, id.vars = c('e', 'row.id'))
for (i in 2:nrow(dat.melt)) {
# This next step is just to ignore the empty values
if (grepl('^[[:space:]]*$', dat.melt$value[i])) {
next
}
earlier.instance <- dat.melt$row.id[which(dat.melt$value[1:(i-1)] == dat.melt$value[i])]
if (length(earlier.instance) > 0) {
earlier.row.id <- earlier.instance[1]
dat.melt$row.id[dat.melt$row.id == dat.melt$row.id[i]] <- earlier.row.id
}
}

这种方法有两个问题。

  1. 可能第 3 行中的某个 ID 与第 1 行匹配,而第 5 行中的另一个 ID 与第 3 行匹配。在这种情况下,第 3 行和第 5 行的行 ID 都应更改为 1。这意味着按顺序浏览行很重要,这导致我使用 for 循环,而不是 apply 函数。我知道这不太像 R,而且对于大数据帧,我使用它的速度非常慢。
  2. 此代码产生以下输出。现在有多行具有相同的 row.idvariable,因此我不知道如何对其进行转换以获得上面显示的输出类型。此处使用 dcast 将强制使用聚合函数。

输出:

   e row.id variable     value
1 1 3 a cat
2 5 2 a canine
3 3 3 a feline
4 8 2 a dog
5 1 3 b feline
6 5 2 b puppy
7 3 3 b meower
8 8 2 b wolf
9 1 3 c kitten
10 5 2 c barker
11 3 3 c kitty
12 8 2 c canine
13 1 3 d shorthair
14 5 2 d collie
15 3 3 d
16 8 2 d

最佳答案

新答案。解决这个问题有一些乐趣(/沮丧)。我确信这不是最快的解决方案,但它应该可以让您超越我的其他答案所停止的位置。让我解释一下:

dat <- data.table(a = c('cat', 'canine', 'feline', 'dog', 'cat','fido'),
b = c('feline', 'puppy', 'meower', 'wolf', 'kitten', 'dog'),
c = c('kit', 'barker', 'kitty', 'canine', 'feline','wolf'),
d = c('shorthair', 'collie', '', '','',''),
e = c(1, 2, 3, 4, 5, 6))

dat[, All := paste(a, b,c),]

两项更改:dat$e现在是索引列,因此它只是其所在行的数字位置。如果e否则很重要,您可以创建一个新列来替换它。

下面是第一个循环。这使得 3 个新列 FirstMatchingID这些就像以前一样:它们给出了最早(最低行号)匹配 dat$All 的索引。对于 a bc .

for(i in 2:nrow(dat)) {
x <- grepl(dat[i]$a, dat[i-(1:i)]$All)
y <- max(which(x %in% TRUE))
dat[i, FirstMatchingID := dat[i-y]$e]

x2 <- grepl(dat[i]$b, dat[i-(1:i)]$All)
y2 <- max(which(x2 %in% TRUE))
dat[i, SecondMatchingID := dat[i-y2]$e]

x3 <- grepl(dat[i]$c, dat[i-(1:i)]$All)
y3 <- max(which(x3 %in% TRUE))
dat[i, ThirdMatchingID := dat[i-y3]$e]

}

接下来,我们使用pmin查找 MatchingID 的最早匹配行列并将其设置在自己的列中。这是为了以防万一您有匹配的 a在第 25 行,匹配 b在第 12 行;它会给你 12 (我认为这是你根据你的问题想要的)。

dat$MinID <- pmin(dat$FirstMatchingID, dat$SecondMatchingID, dat$ThirdMatchingID, na.rm=T)

最后,这个循环将做 3 件事,创建一个 FinalID包含 e 中所有匹配 ID 号的列:

  1. 哪里 MinIDNA (没有匹配项)设置FinalIDe
  2. 如果MinID是一个数字,找到该行(最早的匹配项)并检查其是否为 MinID是一个数字;如果不是,则没有更早的匹配,并且它设置 FinalIDMinID
  3. 不符合上述条件的行是您的特殊情况,其中行 i最早的比赛本身也有更早的比赛。这将找到匹配并将其设置为 FinalID .

for (i in 1:nrow(dat)) {
x <- dat[i]$MinID
if (is.na(dat[i]$MinID)) {
dat[i, FinalID := e]
} else if (is.na(dat[x]$MinID)) {
dat[i, FinalID := MinID]
} else dat[i, FinalID := dat[x]$MinID]
}

我认为这应该可以做到;让我知道事情的后续。我对其效率或速度不做任何声明。

关于r - 基于多列组合 R 中的数据框行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39472193/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com