从这样的数据帧

test <- data.frame('id'= rep(1:5,2), 'string'= LETTERS[1:10])
test <- test[order(test$id), ]
rownames(test) <- 1:10

> test
    id string
 1   1      A
 2   1      F
 3   2      B
 4   2      G
 5   3      C
 6   3      H
 7   4      D
 8   4      I
 9   5      E
 10  5      J

我想用每个id/字符串对的第一行创建一个新的.如果sqldf接受其中的R代码,则查询可能如下所示:

res <- sqldf("select id, min(rownames(test)), string 
              from test 
              group by id, string")

> res
    id string
 1   1      A
 3   2      B
 5   3      C
 7   4      D
 9   5      E

除了创建一个像这样的新专栏,还有什么解决方案吗

test$row <- rownames(test)

并且用min(行)运行相同的sqldf查询?

推荐答案

你可以用duplicated快速完成这项工作.

test[!duplicated(test$id),]

对于速度狂来说,基准是:

ju <- function() test[!duplicated(test$id),]
gs1 <- function() do.call(rbind, lapply(split(test, test$id), head, 1))
gs2 <- function() do.call(rbind, lapply(split(test, test$id), `[`, 1, ))
jply <- function() ddply(test,.(id),function(x) head(x,1))
jdt <- function() {
  testd <- as.data.table(test)
  setkey(testd,id)
  # Initial solution (slow)
  # testd[,lapply(.SD,function(x) head(x,1)),by = key(testd)]
  # Faster options :
  testd[!duplicated(id)]               # (1)
  # testd[, .SD[1L], by=key(testd)]    # (2)
  # testd[J(unique(id)),mult="first"]  # (3)
  # testd[ testd[,.I[1L],by=id] ]      # (4) needs v1.8.3. Allows 2nd, 3rd etc
}

library(plyr)
library(data.table)
library(rbenchmark)

# sample data
set.seed(21)
test <- data.frame(id=sample(1e3, 1e5, TRUE), string=sample(LETTERS, 1e5, TRUE))
test <- test[order(test$id), ]

benchmark(ju(), gs1(), gs2(), jply(), jdt(),
    replications=5, order="relative")[,1:6]
#     test replications elapsed relative user.self sys.self
# 1   ju()            5    0.03    1.000      0.03     0.00
# 5  jdt()            5    0.03    1.000      0.03     0.00
# 3  gs2()            5    3.49  116.333      2.87     0.58
# 2  gs1()            5    3.58  119.333      3.00     0.58
# 4 jply()            5    3.69  123.000      3.11     0.51

让我们再试一次,但是只有第一轮热身的竞争者,有更多的数据和更多的复制.

set.seed(21)
test <- data.frame(id=sample(1e4, 1e6, TRUE), string=sample(LETTERS, 1e6, TRUE))
test <- test[order(test$id), ]
benchmark(ju(), jdt(), order="relative")[,1:6]
#    test replications elapsed relative user.self sys.self
# 1  ju()          100    5.48    1.000      4.44     1.00
# 2 jdt()          100    6.92    1.263      5.70     1.15

R相关问答推荐

R dðr按时间间隔进行总结

在之前合并的数据.tables中分配新列后.internal.selfref无效

替换字符的所有实例,但仅限于匹配字符串中

如何删除多个.CSV文件的行

根据列表中项目的名称多次合并数据框和列表

对lme 4对象运行summary()时出错(diag中的错误(from,names = RST):对象unpackedMatrix_diag_get找不到)

计算R中的威布尔分布的EDF

如何修复R码的置换部分?

如何在ggplot中标记qqplot上的点?

如何在ggplot图中找到第二轴的比例

如何在R forestplot中为多条垂直线分配唯一的 colored颜色 ?

您是否可以使用facet_rap设置一个较低的限制来对ggmap上的比例中断进行zoom ?

R代码,用于在线条图下显示观测表

ggplot R:X,Y,Z使用固定/等距的X,Y坐标绘制六边形热图

数值型数据与字符混合时如何进行绑定

从线的交点创建面

判断函数未加载R中的库

按组和连续id计算日期差

使用ggplot2绘制具有边缘分布的坡度图

如何在R中创建这些列?