【问题标题】:The efficient way of filtering low frequency data in data frame in RR中过滤数据帧中低频数据的有效方法
【发布时间】:2018-07-17 18:37:39
【问题描述】:

我有一个包含几列的data.frame,想根据变量的组合过滤低频数据。该示例就像在性别变量中具有男性/女性和在胆固醇变量中具有高/低一样。那么我的数据框会是这样的:

set.seed(123)
Sex = sample(c('Male','Female'),size = 20,replace = TRUE)
Age = sample(c('Low','High'),size = 20,replace = TRUE)
Index = 1:20
df = data.frame(index = Index,Sex=Sex,Age=Age)
df


  index    Sex  Age
1      1   Male High
2      2 Female High
3      3   Male High
4      4 Female High
5      5 Female High
6      6   Male High
7      7 Female High
8      8 Female High
9      9 Female  Low
10    10   Male  Low
11    11 Female High
12    12   Male High
13    13 Female High
14    14 Female High
15    15   Male  Low
16    16 Female  Low
17    17   Male High
18    18   Male  Low
19    19   Male  Low
20    20 Female  Low

现在我想过滤频率高于3的Sex/Age的组合

table(df[,2:3])
        Age
Sex      High Low
  Female    8   3
  Male      5   4

换句话说,我想保留女性高、男性低和男性高的指数。

注意 1)我的数据框有几个变量(不像上面的例子)和 2)我确实 不想使用任何第三个 R 包和 3)我希望它快。

【问题讨论】:

  • 有充分的理由,为什么你只想使用 Base-R?否则我有一个漂亮而优雅的问题要问你。
  • 我使用多核功能,很难将第三个包传递到程序中
  • df %>% group_by(Sex, Age) %>% mutate(occurences = n())
  • 它在 R 中吗?什么是 R 包?哦 dplyr 是一个有问题的包,我已经尝试过了
  • 好的,所以我在下面发布了一个 Base-R 答案。一个附录:你说你希望它很快。如果这真的很重要,你应该三思而后行。 Dplyr 更快,如果你真的需要它更快,data.table 是你的首选。

标签: r


【解决方案1】:

好的,这是一个 Base-R 选项

set.seed(123)
Sex = sample(c('Male','Female'),size = 20,replace = TRUE)
Age = sample(c('Low','High'),size = 20,replace = TRUE)
Index = 1:20
df = data.frame(index = Index,Sex=Sex,Age=Age)
df

merge(
    df
    , aggregate(rep(1, nrow(df)), by = df[,c("Sex", "Age")], sum)
    , by = c("Sex", "Age")
)

聚合函数sums 将所有1s 的所有组合向上。

【讨论】:

  • 你应该通过df$x添加子集
【解决方案2】:

下面是基本 R 中的一个简单方法:

lvls <- interaction(df$Sex, df$Age)
counts <- table(lvls)
df[lvls %in% names(counts)[counts > 3], ]

#   index    Sex  Age
#1      1   Male High
#2      2 Female High
#3      3   Male High
#4      4 Female High
#5      5 Female High
#6      6   Male High
#7      7 Female High
#8      8 Female High
#10    10   Male  Low
#11    11 Female High
#12    12   Male High
#13    13 Female High
#14    14 Female High
#15    15   Male  Low
#17    17   Male High
#18    18   Male  Low
#19    19   Male  Low

如果你有更多的变量,你可以将它们存储在一个向量中:

vars <- c("Age", "Sex") # add more
lvls <- interaction(df[, vars])
counts <- table(lvls)
df[lvls %in% names(counts)[counts > 3], ]

这是使用ave 的第二种基本 R 方法:

subset(df, ave(as.integer(factor(Sex)), Sex, Age, FUN = "length") > 3)

【讨论】:

    【解决方案3】:

    dplyr 的答案是

    library(dplyr)
    df %>% 
      group_by(Sex, Age) %>% 
      filter(n() > 3) 
    

    即使在 OP 中说明,这也不是基本的 R 解决方案。认为它可能对没有此类限制的未来用户有用。

    【讨论】:

    • 您可以在不使用df %&gt;% group_by(Sex, Age) %&gt;% filter(n() &gt; 3)创建显式变量的情况下执行此操作
    【解决方案4】:
    vars     <- c("Sex","Age")
    max_freq <- 3
    new_df   <- merge(df, subset(as.data.frame(table(df[,vars])),Freq>max_freq)[1:2])
    
    new_df
    #       Sex  Age index
    # 1  Female High     2
    # 2  Female High     7
    # 3  Female High    14
    # 4  Female High    11
    # 5  Female High     5
    # 6  Female High     4
    # 7  Female High    13
    # 8  Female High     8
    # 9    Male High     6
    # 10   Male High     3
    # 11   Male High     1
    # 12   Male High    17
    # 13   Male High    12
    # 14   Male  Low    10
    # 15   Male  Low    15
    # 16   Male  Low    18
    # 17   Male  Low    19
    

    【讨论】:

      【解决方案5】:

      我们可以用data.table 做到这一点,它也应该很有效

      library(data.table)
      setDT(df)[, .SD[.N > 3], .(Sex, Age)]
      

      .I

      setDT(df)[df[, .I[.N >3], .(Sex, Age)]$V1]
      

      【讨论】:

        猜你喜欢
        • 2021-02-16
        • 1970-01-01
        • 1970-01-01
        • 2020-01-16
        • 2016-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多