基于每组行数的子集数据框 [英] Subset data frame based on number of rows per group

查看:33
本文介绍了基于每组行数的子集数据框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的数据,其中某些名称"出现了 3 次以上:

I have data like this, where some "name" occurs more than three times:

df <- data.frame(name = c("a", "a", "a", "b", "b", "c", "c", "c", "c"), x = 1:9)

  name x
1    a 1
2    a 2
3    a 3
4    b 4
5    b 5
6    c 6
7    c 7
8    c 8
9    c 9

我希望根据 name 变量的每个级别内的行数(观察值)对数据进行子集化(过滤).如果某个级别的 name 出现超过 3 次,我想删除属于该级别的所有行.所以在这个例子中,我们将删除 name == c 的观察,因为有 >该组中的 3 行:

I wish to subset (filter) the data based on number of rows (observations) within each level of the name variable. If a certain level of name occurs more than say 3 times, I want to remove all rows belonging to that level. So in this example, we would drop observations where name == c, since there are > 3 rows in that group:

  name x
1    a 1
2    a 2
3    a 3
4    b 4
5    b 5

我写了这段代码,但无法让它工作.

I wrote this code, but can't get it to work.

as.data.frame(table(unique(df)$name))
subset(df, name > 3)

推荐答案

首先,两个 base 替代方案.一个依赖于table,另一个依赖于avelength.然后,两种data.table方式.

First, two base alternatives. One relies on table, and the other on ave and length. Then, two data.table ways.

tt <- table(df$name)

df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]

<小时>

如果你想一步一步来:


If you want to walk it through step by step:

# count each 'name', assign result to an object 'tt'
tt <- table(df$name)

# which 'name' in 'tt' occur more than three times?
# Result is a logical vector that can be used to subset the table 'tt'
tt < 3

# from the table, select 'name' that occur < 3 times
tt[tt < 3]

# ...their names
names(tt[tt < 3])

# rows of 'name' in the data frame that matches "the < 3 names"
# the result is a logical vector that can be used to subset the data frame 'df'
df$name %in% names(tt[tt < 3])

# subset data frame by a logical vector
# 'TRUE' rows are kept, 'FALSE' rows are removed.
# assign the result to a data frame with a new name
df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]

<小时>

2.avelength

正如@flodel 所建议的:


2. ave and length

As suggested by @flodel:

df[ave(df$x, df$name, FUN = length) < 3, ]

<小时>

3.data.table: .N.SD:


3. data.table: .N and .SD:

library(data.table)
setDT(df)[, if (.N < 3) .SD, by = name]

<小时>

4.data.table: .N.I:


4. data.table: .N and .I:

setDT(df)
df[df[, .I[.N < 3], name]$V1] 

<小时>

另见相关问答计算每组的观察数/行数并将结果添加到数据框.

这篇关于基于每组行数的子集数据框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆