【问题标题】:Select rows in a data.frame when some rows repeat当某些行重复时选择data.frame中的行
【发布时间】:2017-03-14 00:33:41
【问题描述】:

我有以下玩具数据集

set.seed(100)
df <- data.frame(ID = rep(1:5, each = 3),
                 value = sample(LETTERS, 15, replace = TRUE),
                 weight = rep(c(0.1, 0.1, 0.5, 0.2, 0.1), each = 3))
df

   ID value weight
1   1     I    0.1
2   1     G    0.1
3   1     O    0.1
4   2     B    0.1
5   2     M    0.1
6   2     M    0.1
7   3     V    0.5
8   3     J    0.5
9   3     O    0.5
10  4     E    0.2
11  4     Q    0.2
12  4     W    0.2
13  5     H    0.1
14  5     K    0.1
15  5     T    0.1

其中每个 ID 是一个单独的受访者,回答 3 个问题(在实际数据集中,回答的问题数量是可变的,因此我不能依赖每个 ID 的特定行数)。

我想创建一个新的(更大的)数据集,它根据weight 中的权重从各个 ID 中采样。

probs <- data.frame(ID = unique(df$ID))
probs$prob <- NA
for(i in 1:nrow(probs)){
  probs$prob[i] <- df[df$ID %in% probs$ID[i],]$weight[1]
}
probs$prob <- probs$prob / sum(probs$prob)
sampledIDs <- sample(probs$ID, size = 10000, replace = TRUE, prob = probs$prob)
head(sampledIDs,10)

[1] 4 3 3 3 4 4 2 4 2 3

从 ID 的概率抽样转移到实际创建新的 data.frame 让我很难过。我试过了

dfW <- df[df$ID %in% sampledIDs,]

但这显然没有考虑到 ID 重复的事实。我也试过循环:

dfW <- df[df$ID == sampledIDs[1],]
for(i in 2:length(sampledIDs)){
  dfW <- rbind(dfW, df[df$ID == sampledIDs[i],])
}

但是对于大型数据集,这非常痛苦

任何帮助将不胜感激。

(另外,如果有更简单的方法来进行 ID 的概率选择,那也太好了!)

【问题讨论】:

  • 你试过包sampling吗?

标签: r


【解决方案1】:

代码速度很低,因为您在for 循环的每个循环中调整数据帧的大小。这是我的建议。创建一个数据框,其最终大小是数据框dfWfor 循环之前将具有的大小。然后在for 循环中将数据框df 中的值分配给dfW。您可以使用以下代码更改代码的最后一部分:

dfW <- as.data.frame(matrix(nrow = 3 * length(sampledIDs), ncol = 3))
colnames(dfW) <- colnames(df)  # make the column names the same
for(i in 1:length(sampledIDs)){ # notice the start index is changed from 2 to 1
    #dfW <- rbind(dfW, df[df$ID == sampledIDs[i],])
    dfW[(3*i-2):(3*i),] <- df[df$ID == sampledIDs[i],]
}

您的代码应该在此更改后运行得更快。告诉我进展如何!

【讨论】:

  • 问题是,我不知道最终的规模是多少,因为真实数据集中的受访者会回答 1 到 10 个问题。
  • 我修改了之前的解决方案并添加了一个函数,当您不知道数据框的最终大小时,该函数可以解决您的问题。希望这个会有所帮助。干杯!
【解决方案2】:

如果您不知道最终大小,您可以随时调整大小,但应在for 循环中添加新的 if 条件。首先定义调整数据框大小的函数如下:

double_rowsize <- function(df) {
  mdf <- as.data.frame(matrix(, nrow = nrow(df), ncol = ncol(df)))
  colnames(mdf) <- colnames(df)
  df <- rbind(df, mdf)
  return(df)
}

然后以 12(3 乘以 4)的初始大小开始 dfW

dfW <- as.data.frame(matrix(nrow = 12, ncol = 3))
colnames(dfW) <- colnames(df)

最后在for 循环中添加一个if 条件,以便在需要时调整数据框的大小:

for(i in 1:length(sampledIDs)){ 
  if (3*i > nrow(dfW))
    dfW <- double_rowsize(dfW)
  dfW[(3*i-2):(3*i),] <- df[df$ID == sampledIDs[i],]
}

您可以更改函数 double_rowsize 的详细信息,以使用不同的数字而不是 2 更改数据帧大小,如果其他方法更好的话。 2 很常见,因为它在调整数组大小时效果最好。

祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多