如何总结保留所有列的 Dataframe

hgqdbh6s  于 2023-05-11  发布在  其他
关注(0)|答案(3)|浏览(74)

考虑以下 Dataframe :

dummy_df <- tibble(
  A=c("ABC", "ABC", "BCD", "CDF", "CDF", "CDF"),
  B=c(0.25, 0.25, 1.23, 0.58, 0.58, 0.58),
  C=c("lorem", "ipsum", "dolor", "amet", "something", "else"),
  D=c("up", "up", "down", "down", "down", "down"),
  E=c(132, 132, 243, 512, 512, 512),
  F=c("m1", "m1", "m5", "m3", "m3", "m3"),
  G=c("val", "val", "mur", "mad", "mad", "mad"),
  H=c("grx", "grx", "bcn", "sal", "sal", "sal"),
  I=c(1.68, 1.68, 2.31, 3.12, 3.12, 3.12),
  J=c("p", "p", "f", "p", "p", "p"),
  K=c(100, 100, 200, 143, 143, 143)
)

# A tibble: 6 × 11
  A         B C         D         E F     G     H         I J         K
  <chr> <dbl> <chr>     <chr> <dbl> <chr> <chr> <chr> <dbl> <chr> <dbl>
1 ABC    0.25 lorem     up      132 m1    val   grx    1.68 p       100
2 ABC    0.25 ipsum     up      132 m1    val   grx    1.68 p       100
3 BCD    1.23 dolor     down    243 m5    mur   bcn    2.31 f       200
4 CDF    0.58 amet      down    512 m3    mad   sal    3.12 p       143
5 CDF    0.58 something down    512 m3    mad   sal    3.12 p       143
6 CDF    0.58 else      down    512 m3    mad   sal    3.12 p       143

在阅读this之后,我设法折叠了列C,以便将其值连接到列A的每个唯一行值的字符串中。

dummy_df %>% group_by(A) %>% summarise(hits = toString(C), nhits=n())

# A tibble: 3 × 3
  A     hits                  nhits
  <chr> <chr>                 <int>
1 ABC   lorem, ipsum              2
2 BCD   dolor                     1
3 CDF   amet, something, else     3

但是,我正在丢失对我来说至关重要的所有其他列信息。在折叠列C时,如何保留有关所有列的信息?理想情况下,应该在不必硬编码列名的情况下完成,因为列的数量可以根据数据集而变化。
我读过this,但是上面的例子没有创建新的变量,所以我不能让它工作。
这就是我要找的

# A tibble: 3 × 12
  A     hits                  nhits     B D         E F     G     H         I J         K
  <chr> <chr>                 <int> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr> <dbl>
1 ABC   lorem, ipsum              2  0.25 up      132 m1    val   grx    1.68 p       100
2 BCD   dolor                     1  1.23 down    243 m5    mur   bcn    2.31 f       200
3 CDF   amet, something, else     3  0.58 down    512 m3    mad   sal    3.12 p       143
bzzcjhmw

bzzcjhmw1#

如果我们假设除了C之外的所有字段都包含每个A-组的重复值,那么我们可以这样做:

dummy_df %>%
  group_by(A) %>%
  summarize(
    nhits = n(),
    across(where(is.character), ~ toString(unique(.))),
    across(where(~ !is.character(.)), ~ unique(.))
  ) %>%
  ungroup()
# # A tibble: 3 × 12
#   A     nhits C                     D     F     G     H     J         B     E     I     K
#   <chr> <int> <chr>                 <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
# 1 ABC       2 lorem, ipsum          up    m1    val   grx   p      0.25   132  1.68   100
# 2 BCD       1 dolor                 down  m5    mur   bcn   f      1.23   243  2.31   200
# 3 CDF       3 amet, something, else down  m3    mad   sal   p      0.58   512  3.12   143

在这种情况下,由于所有其他变量都是重复的,所以一切都保持原样。然而,如果我们有可变性,那么我已经设置了一个catch,其中字符串被组合(使用toString),不同的数字会导致重复行。

dummy_df$H[1] <- "GRX"
dummy_df$K[1] <- 99
 %>%
  group_by(A) %>%
  summarize(
    nhits = n(),
    across(where(is.character), ~ toString(unique(.))),
    across(where(~ !is.character(.)), ~ unique(.))
  ) %>%
  ungroup()
# A tibble: 4 × 12
  A     nhits C                     D     F     G     H        J         B     E     I     K
  <chr> <int> <chr>                 <chr> <chr> <chr> <chr>    <chr> <dbl> <dbl> <dbl> <dbl>
1 ABC       2 lorem, ipsum          up    m1    val   GRX, grx p      0.25   132  1.68    99
2 ABC       2 lorem, ipsum          up    m1    val   GRX, grx p      0.25   132  1.68   100
3 BCD       1 dolor                 down  m5    mur   bcn      f      1.23   243  2.31   200
4 CDF       3 amet, something, else down  m3    mad   sal      p      0.58   512  3.12   143

across函数迭代多个列。where函数允许我们根据列的值对列进行子集划分,其中对于character列,我们将应用toString,对于其他列,我们将使用unique。这意味着字符串列永远不应该添加行,但非字符串可以添加行。
类似数字的列的一个替代方案是使用first(.)而不是unique(.),这将按组默默地丢弃每列中除第一个值之外的所有值。使用相同的修改后的数据,我们会看到这一点,其中关键的区别是K已经丢弃了100值,因为第一个值是99

dummy_df %>%
  group_by(A) %>%
  summarize(
    nhits = n(), 
    across(where(is.character), ~ toString(unique(.))),
    across(where(~ !is.character(.)), ~ first(.))
  ) %>%
  ungroup()
# # A tibble: 3 × 12
#   A     nhits C                     D     F     G     H        J         B     E     I     K
#   <chr> <int> <chr>                 <chr> <chr> <chr> <chr>    <chr> <dbl> <dbl> <dbl> <dbl>
# 1 ABC       2 lorem, ipsum          up    m1    val   GRX, grx p      0.25   132  1.68    99
# 2 BCD       1 dolor                 down  m5    mur   bcn      f      1.23   243  2.31   200
# 3 CDF       3 amet, something, else down  m3    mad   sal      p      0.58   512  3.12   143

如果你愿意,你也可以选择使用first和字符串列,这可以将逻辑简化为一个across

dummy_df %>%
  group_by(A) %>%
  summarize(
    nhits = n(),
    across(everything(), ~ first(.))
  ) %>%
  ungroup()
# # A tibble: 3 × 12
#   A     nhits     B C     D         E F     G     H         I J         K
#   <chr> <int> <dbl> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr> <dbl>
# 1 ABC       2  0.25 lorem up      132 m1    val   GRX    1.68 p        99
# 2 BCD       1  1.23 dolor down    243 m5    mur   bcn    2.31 f       200
# 3 CDF       3  0.58 amet  down    512 m3    mad   sal    3.12 p       143

请注意,我们丢失了H"grx"(因为"GRX"是第一个)以及K100值。
这个最后一个码块的data.table变体可以简单地是:

library(data.table)
as.data.table(dummy_df)[, c(.(nhits = .N), lapply(.SD, first)), by = A]

和一个R基地的表演也许不像“漂亮”:-)

Reduce(
  function(a, b) merge(a, b, by = "A", all = TRUE), 
  list(
    setNames(aggregate(C ~ A, dummy_df, FUN = length), c("A", "nhits")), 
    aggregate(C ~ A, dummy_df, FUN = toString),
    aggregate(. ~ A, subset(dummy_df, select = -C), FUN = function(z) z[1])
  )
)
#     A nhits                     C    B    D   E  F   G   H    I J   K
# 1 ABC     2          lorem, ipsum 0.25   up 132 m1 val GRX 1.68 p  99
# 2 BCD     1                 dolor 1.23 down 243 m5 mur bcn 2.31 f 200
# 3 CDF     3 amet, something, else 0.58 down 512 m3 mad sal 3.12 p 143
raogr8fs

raogr8fs2#

我们可以这样做:

library(dplyr) #>= 1.1.0
dummy_df %>%
  summarise(hits = toString(C), nhits = n(), B = unique(B), .by = A)

library(dplyr)

dummy_df %>%
  group_by(A) %>%
  summarise(hits = toString(C), nhits = n(), B = unique(B))
A     hits                  nhits     B
  <chr> <chr>                 <int> <dbl>
1 ABC   lorem, ipsum              2  0.25
2 BCD   dolor                     1  1.23
3 CDF   amet, something, else     3  0.58
>
qmelpv7a

qmelpv7a3#

使用data.table

library(data.table)
setDT(dummy_df)[, .(B = first(B), hits = toString(C), nhits = .N), by = A]

相关问题