3

私はデータセットを持っています

dtf<-data.frame(id=c("A","A","A","A","B","B","B","B"), value=c(2,4,6,8,4,6,8,10))

すべての ID について、値は昇順でソートされます

id値が指定された制限を超えるたびに、最初の行のみを含めるように dtf を減らしたいです。idごとに1 行のみでvalue、指定された制限を最初に超えた行になります。

この例と5dtf の制限については、次のように減らす必要があります。

A 6
B 6

これを行う良い方法はありますか?

どうもありがとう

4

5 に答える 5

5

それはで行うことができますaggregate

dtf<-data.frame(id=c("A","A","A","A","B","B","B","B"), value=c(2,4,6,8,4,6,8,10))

limit <- 5

aggregate(value ~ id, dtf, function(x) x[x > limit][1])

結果:

  id value
1  A     6
2  B     6

更新:複数の列のソリューション:

データ フレームの例dtf2:

dtf2 <- data.frame(id=c("A","A","A","A","B","B","B","B"), 
                   value=c(2,4,6,8,4,6,8,10),
                   col3 = letters[1:8],
                   col4 = 1:8)

以下を含むソリューションave:

with(dtf2, dtf2[ave(value, id, FUN = function(x) cumsum(x > limit)) == 1, ])

結果:

  id value col3 col4
3  A     6    c    3
6  B     6    f    6
于 2012-12-22T18:18:40.457 に答える
4

を使用した「素敵な」オプションは次のdata.tableとおりです。

library(data.table)
DT <- data.table(dft, key = "id")

DT[value > 5, head(.SD, 1), by = key(DT)]
#    id value
# 1:  A     6
# 2:  B     6

そして、共有の精神から、sqldfSQL に慣れているかどうかに応じて、 which を使用するオプションが良いかもしれません。

sqldf("select id, min(value) as value from dtf where value > 5 group by id")
#   id value
# 1  A     6
# 2  B     6

更新: 順序付けられていないソース データ、およびdata.frame複数の列を持つ

いくつかの回答に対するコメントに基づいて、「値」列が例のように順序付けられていない可能性があり、data.frame.

これらのシナリオの 2 つの代替案を次に示します。1 つはdata.table、最も読みやすく、おそらく最も高速であると思われる .

まず、いくつかのサンプル データ:

dtf2 <- data.frame(id = c("A","A","A","A","B","B","B","B"),
                   value = c(6,4,2,8,4,10,8,6),
                   col3 = letters[1:8],
                   col4 = 1:8)
dtf2 # Notice that the value column is not ordered
#   id value col3 col4
# 1  A     6    a    1
# 2  A     4    b    2
# 3  A     2    c    3
# 4  A     8    d    4
# 5  B     4    e    5
# 6  B    10    f    6
# 7  B     8    g    7
# 8  B     6    h    8

第二に、data.tableアプローチ:

library(data.table)
DT <- data.table(dtf2)
DT # Verify that the data are not ordered
#    id value col3 col4
# 1:  A     6    a    1
# 2:  A     4    b    2
# 3:  A     2    c    3
# 4:  A     8    d    4
# 5:  B     4    e    5
# 6:  B    10    f    6
# 7:  B     8    g    7
# 8:  B     6    h    8
DT[order(value)][value > 5, head(.SD, 1), by = "id"]
#    id value col3 col4
# 1:  A     6    a    1
# 2:  B     6    h    8

次に、ベース R の一般的な「分割-適用-結合」アプローチ:

do.call(rbind,
        lapply(split(dtf2, dtf2$id), 
               function(x) x[x$value > 5, ][which.min(x$value[x$value > 5]), ]))
#   id value col3 col4
# A  A     6    a    1
# B  B     6    h    8
于 2012-12-22T18:36:03.853 に答える