我有这样的数据,其中Average是X,Y和Z的平均值。
head(df)
ID X Y Z Average
A 2 2 5 3
A 4 3 2 3
A 4 3 2 3
B 5 3 1 3
B 3 4 2 3
B 1 5 3 3
C 5 3 1 3
C 2 3 4 3
C 5 3 1 3
D 2 3 4 3
D 3 2 4 3
D 3 2 4 3
E 5 3 1 3
E 4 3 2 3
E 3 4 2 3
为了重现这一点,我们可以使用
df <- data.frame(ID = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D", "E", "E", "E"),
X = c(2L, 4L, 4L, 5L, 3L,1L, 5L, 2L, 5L, 2L, 3L, 3L, 5L, 4L, 3L),
Y = c(2L, 3L, 3L, 3L,4L, 5L, 3L, 3L, 3L, 3L, 2L, 2L, 3L, 3L, 4L),
Z = c(5L, 2L, 2L,1L, 2L, 3L, 1L, 4L, 1L, 4L, 4L, 4L, 1L, 2L, 2L),
Average = c(3L,3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L))
由此,我想为每个ID提取一个观察值,以便我们得到X,Y和Z组合的相同值(尽可能多)。我试过
library(dplyr)
df %>% sample_n(size = nrow(.), replace = FALSE) %>% distinct(ID, .keep_all = T)
但是,在更大的数据集中,我看到X,Y,Z组合的重复次数太多。在可能的范围内,我需要输出具有相等或接近相等的情况表示(即X的组合, Y,Y)是这样的:
ID X Y Z Average
A 2 2 5 3
B 5 3 1 3
C 2 3 4 3
D 3 2 4 3
E 4 3 2 3
答案 0 :(得分:2)
这看起来很可疑,但试试这个:
library(dplyr)
df %>% add_count(X, Y, Z) %>%
group_by(ID) %>%
top_n(-1, n) %>%
arrange(runif(n)) %>%
select(-n) %>%
slice(1)
# # A tibble: 5 x 5
# # Groups: ID [5]
# ID X Y Z Average
# <fctr> <int> <int> <int> <int>
# 1 A 2 2 5 3
# 2 B 1 5 3 3
# 3 C 2 3 4 3
# 4 D 3 2 4 3
# 5 E 3 4 2 3
这会从每个ID中选择最不常见的XYZ组合,如果是平局,则选择随机选择。非常常见的XYZ组合可能完全缺失。
答案 1 :(得分:1)
这是一种方法。内联说明。请注意,可以根据所需的&#34;相似性&#34; /&#34;复制&#34;行之间。
# get the sample data from the original post
dat <- data.frame(
ID = c("A","A","A","B", "B", "B", "C", "C", "C", "D", "D", "D", "E", "E", "E"),
X = c(2L, 4L, 4L, 5L, 3L,1L, 5L, 2L, 5L, 2L, 3L, 3L, 5L, 4L, 3L),
Y = c(2L, 3L, 3L, 3L,4L, 5L, 3L, 3L, 3L, 3L, 2L, 2L, 3L, 3L, 4L),
Z = c(5L, 2L, 2L,1L, 2L, 3L, 1L, 4L, 1L, 4L, 4L, 4L, 1L, 2L, 2L),
Average = c(3L,3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L))
定义一个函数,该函数对给定id的数据帧的一行进行采样(假设存在$ID
列):
# function to get a randomly sampled row from `df` with `df$ID==id`
id_sample <- function(df, id){
df <- df[df$ID==id, ]
return(df[sample(1:nrow(df), size=1), ])
}
定义一个循环遍历每个id的函数,如果样本过于相似则拒绝样本&#34;到数据框中已有的行:
make_sample_df <- function(dat, threshold){
# initialize empty data frame to fill with row samples
out <- dat[NULL, ]
# get the unique id's to loop over
ids <- unique(dat$ID)
for (id in ids){
# grab a sample
id_row <- id_sample(dat, id)
# see how many of its elements have column-duplicates (zero for first id)
n_dupes <- sum(apply(out, 1, function(row){
sum(row[1]==id_row$X, row[2]==id_row$Y, row[3]==id_row$Z)}))
# keep getting samps if the number of duplicates is higher than threshold
while (n_dupes > threshold){
id_row <- id_sample(dat, id)
n_dupes <- sum(apply(out, 1, function(row){
sum(row[1]==id_row$X, row[2]==id_row$Y, row[3]==id_row$Z)}))
}
# once we have a suitable row for `id`, add it to the output df
out <- rbind(out, id_row)
}
return(out)
}
现在将func应用于OP的数据并检查:
# rows at most 1 of whose values appear in another row (at same column)
set.seed(6933)
make_sample_df(dat, threshold=1)
## ID X Y Z Average
## A 4 3 2 3
## B 1 5 3 3
## C 2 3 4 3
## D 3 2 4 3
## E 5 3 1 3
根据您的需要,您可以尝试不同的threshold
值,但请注意,如果您对threshold
过于严格,while
循环可能会永远保持运行,因此你可能想在那里放一些逃生舱。
您还可以根据不同的变化调整此策略,例如:您关心在行内而不是列中重复的值的地方。
希望这有帮助~~
答案 2 :(得分:0)
一种可能的解决方案可能是filtered_proj=fft(s).*filter;
proj=real(ifft(filtered_proj));
值,这些值已针对上一列进行了采样。
excluding
我更改了列名,只是让逻辑清晰。
答案 3 :(得分:0)
我只是想补充一下左边的答案。 我修改了代码以允许样本大小,而不依赖于具有名为 ID 或 X、Y、Z 或其中任何一个的列
id_sample <- function(df, id, field, sampleSize) {
df = df %>%
filter(!!as.symbol(field) == id)
return(df[sample(1:nrow(df), size = sampleSize, replace = TRUE),])
}
make_sample_df <- function(dat, sampleSize, field) {
# initialize empty data frame to fill with row samples
out <- dat[NULL,]
# get the unique id's to loop over
ids <- unique(dat[[field]])
for (id in ids) {
# grab a sample
id_row <- id_sample(dat, id, field,sampleSize)
out <- rbind(out, id_row)
}
return(out)
}
然后我如何使用它
sample_df = make_sample_df(df, 20, "ColumnToSampleOn")
其中 df 是我的原始数据框,20 是我想要在“ColumnToSampleOn”中找到的每个唯一值的行数
如果这对你有帮助,也请点赞 leftts original answer,因为它奠定了基础