【问题标题】:R - Compare and delete rows with identical column value in data frame while keeping one of themR - 比较和删除数据框中具有相同列值的行,同时保留其中一个
【发布时间】:2013-04-03 16:34:51
【问题描述】:

我有一个数据框,它由几行组成,“名称”列中的值相同,但“距离”列中的值不同。我想删除“名称”中具有相同条目的所有行,只保留距离最小的行。有没有比比较所有行更简单的方法,并在比较它们的“距离”值之前检查它们的“名称”条目是否相同?真实的数据框大约是 14000 行 x 14 列。 我一直在寻找答案,但还没有找到任何东西,所以我会非常感谢任何帮助!

这将是原始数据框:

     name      distance number
[1,] "apple"   "2.5"    "4"   
[2,] "banana"  "3"      "6"   
[3,] "apple"   "1"      "2"   
[4,] "satsuma" "4"      "8"   
[5,] "satsuma" "7.5"    "1"   
[6,] "melon"   "3"      "3"   
[7,] "satsuma" "1"      "6"  

这是我想要得到的(不一定是这个顺序):

     name      distance number
[1,] "banana"  "3"      "6"   
[2,] "apple"   "1"      "2"   
[3,] "melon"   "3"      "3"   
[4,] "satsuma" "1"      "6"   

【问题讨论】:

  • 这不是一个data.frame,而是一个矩阵。

标签: r dataframe


【解决方案1】:

首先,按namedistance 对data.frame 进行排序,然后将要保留的行标记为每个名称的前几行:

sorted <- dat[order(dat$name, dat$distance), ]

keep <- c(TRUE, head(sorted$name,-1) != tail(sorted$name,-1))

结果是

sorted[keep, ]

【讨论】:

  • 是的,这可能是最快的方法。 +1
【解决方案2】:

您可以使用aggregatemerge,如下所示

DF <- read.table(text='name      distance number
apple   2.5    4   
banana  3      6   
apple   1      2   
satsuma 4      8   
satsuma 7.5    1   
melon   3      3   
satsuma 1      6', header=TRUE)

merge(DF, aggregate(distance ~ name, data = DF, min))
##      name distance number
## 1   apple        1      2
## 2  banana        3      6
## 3   melon        3      3
## 4 satsuma        1      6

【讨论】:

  • 不错的方法。永远不会想到这一点。 +1
【解决方案3】:

几点开始:

让您的数据尽可能易于他人阅读。 dput(head(your_data)) 是一个很好的方法。还有两个你的数据在一个矩阵而不是一个数据框中,所以你的数据类型是字符的限制最少,所以你的所有数据都是一个字符。我认为在这里将其存储为 data.frame 更好,因为您有混合数据类型。因此,我立即将您的数据作为数据框读取,并确保距离列是数字。

dat <- read.table(text='
name      distance number
"apple"   "2.5"    "4"   
"banana"  "3"      "6"   
"apple"   "1"      "2"   
"satsuma" "4"      "8"   
"satsuma" "7.5"    "1"   
"melon"   "3"      "3"   
"satsuma" "1"      "6"', header=T)  

dat$distance <- as.numeric(dat$distance)


#split by grouping variable
splitdat <- split(dat, dat$name)

#find the minimum distance and index that 
out <- lapply(splitdat, function(x) {
    x[which.min(x$distance), ]
})

#put it all back together as a data frame
data.frame(do.call(rbind, out), row.names=NULL)

这是众多方法之一。

【讨论】:

  • 有用的新手建议。 lapply(split(..,..)) 范式与我使用的 by 非常相似。
  • 感谢您的回答和建议!这是我在这里的第一个问题,我试图使其尽可能通用(我的真实数据是数据框而不是矩阵)。
【解决方案4】:

我看到了@geektrader 的聚合合并方法,但想知道合并是否会占用 CPU 和内存:

do.call(rbind, by( DF, DF['name'], function(d) d[which.min(d$distance), ] ) )
           name distance number
apple     apple        1      2
banana   banana        3      6
melon     melon        3      3
satsuma satsuma        1      6

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 2017-01-10
    • 2012-01-13
    • 2014-06-23
    • 2018-08-09
    • 1970-01-01
    • 2021-09-12
    相关资源
    最近更新 更多