按因子级别对数据进行分组,然后转换为名称为级别的数据框?

时间:2018-12-14 02:21:19

标签: r dataframe

我的问题无法解决:

数据:

df <- data.frame(f1=c("a", "a", "b", "b", "c", "c", "c"), 
                 v1=c(10, 11, 4, 5, 0, 1, 2))

data.frame:f1 is factor
  f1 v1
  a   10
  a   11
  b   4
  b   5
  c   0
  c   1   
  c   2
 # What I want is:(for example, fetch data with the number of element of some level == 2, then to data.frame)
  a   b
 10   4
 11   5  

谢谢!

5 个答案:

答案 0 :(得分:2)

在这里我可能会遗漏一些简单的东西,但是下面使用dplyr的方法是可行的。

library(dplyr)
nlevels = 2

df1 <- df %>%
        add_count(f1) %>%
        filter(n == nlevels) %>%
        select(-n) %>%
        mutate(rn = row_number()) %>%
        spread(f1, v1) %>%
        select(-rn)

这给

#      a     b
#   <int> <int>
#1    10    NA
#2    11    NA
#3    NA     4
#4    NA     5

现在,如果您要删除NA,我们可以

do.call("cbind.data.frame", lapply(df1, function(x) x[!is.na(x)]))

#   a b
#1 10 4
#2 11 5

由于我们过滤了只有nlevels个观察值的数据框,所以最终数据框中的每一列将具有相同数量的行。

答案 1 :(得分:2)

split在这里可能有用,可以将df$v1拆分为与df$f1相对应的部分。由于您总是提取等长的块,因此可以将其简单地组合回data.frame

spl <- split(df$v1, df$f1)
data.frame(spl[lengths(spl)==2])

#   a b
#1 10 4
#2 11 5

或者通过将其与Filter组合在一起,一次完成所有操作:

data.frame(Filter(function(x) length(x)==2, split(df$v1, df$f1)))
#   a b
#1 10 4
#2 11 5

答案 2 :(得分:1)

这是使用unstack的解决方案:

unstack(
  droplevels(df[ave(df$v1, df$f1, FUN = function(x) length(x) == 2)==1,]),
  v1 ~ f1)
#    a b
# 1 10 4
# 2 11 5

一个变种,类似于@thelatemail的解决方案:

data.frame(Filter(function(x) length(x) == 2, unstack(df,v1 ~ f1)))

我的 tidyverse 解决方案是:

library(tidyverse)
df                  %>%
  group_by(f1)      %>%
  filter(n() == 2)  %>%
  mutate(i = row_number()) %>%
  spread(f1, v1)   %>%
  select(-i)
# # A tibble: 2 x 2
#       a     b
# * <dbl> <dbl>
# 1    10     4
# 2    11     5

或混合方法:

as_tibble(keep(unstack(df,v1 ~ f1), ~length(.x) == 2))

答案 3 :(得分:0)

我想要这样的代码,可能对您有帮助

library(reshape2)

library(dplyr)

aa = data.frame(v1=c('a','a','b','b','c','c','c'),f1=c(10,11,4,5,0,1,2))

cc = aa %>% group_by(v1) %>% summarise(id = length((v1))) 

dd= merge(aa,cc) #get the level 

ee = dd[dd$aa==2,] #select number of level equal to 2

ee$id = rep(c(1,2),nrow(ee)/2) # reset index like (1,2,1,2)

dcast(ee, id~v1,value.var = 'f1')

全部完成!

答案 4 :(得分:0)

使用所有基本功能(但您应该使用tidyverse)

# Add count of instances
x$len <- ave(x$v1, x$f1, FUN = length)

# Filter, drop the count
x <- x[x$len==2, c('f1','v1')]

# Hacky pivot
result <- data.frame(
lapply(unique(x$f1), FUN = function(y) x$v1[x$f1==y])
)
colnames(result) <- unique(x$f1)

> result
   a b
1 10 4
2 11 5