R语言 将数据框减少到更少的行

o7jaxewo  于 2023-07-31  发布在  其他
关注(0)|答案(6)|浏览(108)

假设我有一个 Dataframe “dat”,如:

col1     col2
  12       a
  43       a
  54       a
  11       a
  33       b
  43       b
  34       c
  34       c
  342      c
  343      c

字符串
现在我有一个向量

vec <- c(a,a,a,b,c,c)


我想要做的是按照向量“vec”移除 Dataframe “dat”中的额外行,这意味着在 Dataframe 中仅保留对应于“a”的前3行,仅保留对应于“B”的前1行,并且仅保留对应于c的前2行。
我应该得到输出为

col1     col2
  12       a
  43       a
  54       a
  33       b
  34       c
  34       c


不使用for循环的最快方法是什么?

tjjdgumg

tjjdgumg1#

这也可以通过在创建序列列后执行

library(data.table)
setkey(setDT(dat)[, N:= 1:.N, col2], col2, N)
dat[setDT(list(col2=vec))[, N:=1:.N, col2]][, N:= NULL][]
#   col1 col2
#1:   12    a
#2:   43    a
#3:   54    a
#4:   33    b
#5:   34    c
#6:   34    c

字符串

jqjz2hbq

jqjz2hbq2#

下面是使用splitMap的方法:

数据

dat <- read.table(header=T, text=' col1     col2
  12       a
  43       a
  54       a
  11       a
  33       b
  43       b
  34       c
  34       c
  342      c
  343      c',stringsAsFactors=F)

vec <-  c('a','a','a','b','c','c')

字符串

解决方案

#count frequencies
tabvec <- table(vec)

data.frame(do.call(rbind,
   #use split to split data.frame according to col2
   #use head to only choose the first n rows according to tabvec
   #convert output into a data.frame
   Map(function(x,y) head(x,y),  split(dat, as.factor(dat$col2)), tabvec)
))

输出:

col1 col2
a.1   12    a
a.2   43    a
a.3   54    a
b     33    b
c.7   34    c
c.8   34    c

z9smfwbn

z9smfwbn3#

使用dplyr,你可以做到:

#create a data frame with frequencies
tv <- data.frame(table(vec))

#filter values       
group_by(dat, col2) %>%
filter(row_number() <= tv$Freq[tv$vec %in% col2])

字符串
其给出:

#Source: local data frame [6 x 2]
#Groups: col2
#
#  col1 col2
#1   12    a
#2   43    a
#3   54    a
#4   33    b
#5   34    c
#6   34    c

chy5wohz

chy5wohz4#

下面是另一种Map()方法。

fvec <- factor(vec)
## find the index for the first occurrence of a new level
m <- match(levels(fvec), df$col2)

df[unlist(Map(seq, from = m, length.out = tabulate(fvec))), ]
#   col1 col2
# 1   12    a
# 2   43    a
# 3   54    a
# 5   33    b
# 7   34    c
# 8   34    c

字符串
也可以在匹配后使用rle()

rl <- rle(match(vec, df$col2))
df[unlist(Map(seq, rl$values, length.out = rl$lengths)),]
#   col1 col2
# 1   12    a
# 2   43    a
# 3   54    a
# 5   33    b
# 7   34    c
# 8   34    c

sz81bmfz

sz81bmfz5#

使用Base R函数可以完成:

数据

dat <- read.table(header=T, text=
   ' col1     col2
      12       a
      43       a
      54       a
      11       a
      33       b
      43       b
      34       c
      34       c
      342      c
      343      c')
    
    vec <-  c('a','a','a','b','c','c')

字符串

流程

dat[unlist(lapply(table(vec), function(x) 1:x))+match(vec, dat[,2])-1,]

输出

col1 col2
1   12    a
2   43    a
3   54    a
5   33    b
7   34    c
8   34    c

wbrvyc0a

wbrvyc0a6#

使用Base R,可以像下面这样使用subset + ave + table

> subset(df, ave(col2, col2, FUN = seq_along) <= table(vec)[col2])
  col1 col2
1   12    a
2   43    a
3   54    a
5   33    b
7   34    c
8   34    c

字符串

相关问题