programing

dplyr 요약:출력에서 길이가 0인 그룹을 유지하려면 ".drop=FALSE"와 같습니다.

telebox 2023. 6. 26. 21:14
반응형

dplyr 요약:출력에서 길이가 0인 그룹을 유지하려면 ".drop=FALSE"와 같습니다.

사용 시summarise와 함께plyrddply함수의 경우 비어 있는 범주는 기본적으로 삭제됩니다.다음을 추가하여 이 동작을 변경할 수 있습니다..drop = FALSE하지만, 이것은 사용할 때 작동하지 않습니다.summarise와 함께dplyr결과에서 빈 범주를 유지하는 다른 방법이 있습니까?

여기 가짜 데이터의 예가 있습니다.

library(dplyr)

df = data.frame(a=rep(1:3,4), b=rep(1:2,6))

# Now add an extra level to df$b that has no corresponding value in df$a
df$b = factor(df$b, levels=1:3)

# Summarise with plyr, keeping categories with a count of zero
plyr::ddply(df, "b", summarise, count_a=length(a), .drop=FALSE)

  b    count_a
1 1    6
2 2    6
3 3    0

# Now try it with dplyr
df %.%
  group_by(b) %.%
  summarise(count_a=length(a), .drop=FALSE)

  b     count_a .drop
1 1     6       FALSE
2 2     6       FALSE

정확히 제가 기대했던 것과는 다릅니다.있습니까?dplyr와 동일한 결과를 얻기 위한 방법.drop=FALSEplyr?

이 문제는 아직 해결되지 않았지만, 그 동안 특히 데이터가 이미 고려되었기 때문에 다음을 사용할 수 있습니다.complete당신이 찾고 있을 수 있는 것을 얻기 위해 "hyper"로부터:

library(tidyr)
df %>%
  group_by(b) %>%
  summarise(count_a=length(a)) %>%
  complete(b)
# Source: local data frame [3 x 2]
# 
#        b count_a
#   (fctr)   (int)
# 1      1       6
# 2      2       6
# 3      3      NA

대체 값을 0으로 설정하려면 다음과 같이 지정해야 합니다.fill:

df %>%
  group_by(b) %>%
  summarise(count_a=length(a)) %>%
  complete(b, fill = list(count_a = 0))
# Source: local data frame [3 x 2]
# 
#        b count_a
#   (fctr)   (dbl)
# 1      1       6
# 2      2       6
# 3      3       0

dplyr 0.8 이후 group_by을 획득했습니다..drop당신이 요청한 대로 하는 주장:

df = data.frame(a=rep(1:3,4), b=rep(1:2,6))
df$b = factor(df$b, levels=1:3)

df %>%
  group_by(b, .drop=FALSE) %>%
  summarise(count_a=length(a))

#> # A tibble: 3 x 2
#>   b     count_a
#>   <fct>   <int>
#> 1 1           6
#> 2 2           6
#> 3 3           0

@Moody_Mudskipper의 답변과 함께 할 한 가지 추가 참고 사항: 사용.drop=FALSE하나 이상의 그룹화 변수가 요인으로 코드화되지 않은 경우 잠재적으로 예상치 못한 결과를 얻을 수 있습니다.아래의 예를 참조하십시오.

library(dplyr)
data(iris)

# Add an additional level to Species
iris$Species = factor(iris$Species, levels=c(levels(iris$Species), "empty_level"))

# Species is a factor and empty groups are included in the output
iris %>% group_by(Species, .drop=FALSE) %>% tally

#>   Species         n
#> 1 setosa         50
#> 2 versicolor     50
#> 3 virginica      50
#> 4 empty_level     0

# Add character column
iris$group2 = c(rep(c("A","B"), 50), rep(c("B","C"), each=25))

# Empty groups involving combinations of Species and group2 are not included in output
iris %>% group_by(Species, group2, .drop=FALSE) %>% tally

#>   Species     group2     n
#> 1 setosa      A         25
#> 2 setosa      B         25
#> 3 versicolor  A         25
#> 4 versicolor  B         25
#> 5 virginica   B         25
#> 6 virginica   C         25
#> 7 empty_level <NA>       0

# Turn group2 into a factor
iris$group2 = factor(iris$group2)

# Now all possible combinations of Species and group2 are included in the output, 
#  whether present in the data or not
iris %>% group_by(Species, group2, .drop=FALSE) %>% tally

#>    Species     group2     n
#>  1 setosa      A         25
#>  2 setosa      B         25
#>  3 setosa      C          0
#>  4 versicolor  A         25
#>  5 versicolor  B         25
#>  6 versicolor  C          0
#>  7 virginica   A          0
#>  8 virginica   B         25
#>  9 virginica   C         25
#> 10 empty_level A          0
#> 11 empty_level B          0
#> 12 empty_level C          0

Created on 2019-03-13 by the reprex package (v0.2.1)

dplyr 솔루션:

먼저 그룹화된 df를 만듭니다.

by_b <- tbl_df(df) %>% group_by(b)

그런 다음 우리는 다음과 같이 계산함으로써 발생하는 수준을 요약합니다.n()

res <- by_b %>% summarise( count_a = n() )

그런 다음 모든 요인 수준을 포함하는 데이터 프레임에 결과를 병합합니다.

expanded_res <- left_join(expand.grid(b = levels(df$b)),res)

마지막으로, 우리가 카운트를 보고 있기 때문에 이 경우에.NA값이 0으로 변경됩니다.

final_counts <- expanded_res[is.na(expanded_res)] <- 0

이는 기능적으로도 구현할 수 있습니다. 답변을 참조하십시오.dplyr을 사용하여 그룹화된 데이터에 행을 추가하시겠습니까?

해킹:

저는 이자를 위해 이 사건에서 작동하는 끔찍한 해킹을 게시할 것이라고 생각했습니다.나는 당신이 실제로 이것을 해야 하는지 심각하게 의심스럽지만 그것은 어떻게 하는지 보여줍니다.group_by()다음과 같이 속성을 생성합니다.df$b수준이 있는 요인이 아닌 문자 벡터입니다.또한, 저는 이것을 제대로 이해하는 척하지 않습니다. 하지만 이것이 제가 배우는 데 도움이 되기를 바랍니다. 이것이 제가 그것을 게시하는 유일한 이유입니다!

by_b <- tbl_df(df) %>% group_by(b)

데이터 집합에 존재할 수 없는 "사용할 수 없는" 값을 정의합니다.

oob_val <- nrow(by_b)+1

속성을 "trick"으로 수정summarise():

attr(by_b, "indices")[[3]] <- rep(NA,oob_val)
attr(by_b, "group_sizes")[3] <- 0
attr(by_b, "labels")[3,] <- 3

요약을 수행합니다.

res <- by_b %>% summarise(count_a = n())

ob_val의 모든 항목 색인화 및 바꾸기

res[res == oob_val] <- 0

이는 의도된 것을 제공합니다.

> res
Source: local data frame [3 x 2]

b count_a
1 1       6
2 2       6
3 3       0

질문에서 질문한 내용은 정확하지 않지만 적어도 이 간단한 예제의 경우 다음과 같은 xtab을 사용하여 동일한 결과를 얻을 수 있습니다.

dplyr 사용:

df %>%
  xtabs(formula = ~ b) %>%
  as.data.frame()

또는 더 짧습니다.

as.data.frame(xtabs( ~ b, df))

결과(두 경우 모두 포함):

  b Freq
1 1    6
2 2    6
3 3    0

언급URL : https://stackoverflow.com/questions/22523131/dplyr-summarise-equivalent-of-drop-false-to-keep-groups-with-zero-length-in

반응형