在一个数据框架中,通过ID和不同的列类型,R组合重复的行。

问题描述 投票:0回答:1

我有一个数据框,其中有一个列ID作为标识符,还有一些其他不同类型的列(因子和数字)。它看起来像这样

df <- data.frame(id    = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4),
                 abst  = c(0, NA, 2, NA, NA, NA, 0, 0, NA, 2, NA, 3, 4),
                 farbe = as.factor(c("keine", NA, "keine", NA, NA, NA, "keine", "keine", NA, NA, NA, "rot", "rot")),
                 gier  = c(0, NA, 5, NA, NA, NA, 0, 0, NA, 1, NA, 6, 2))

现在我想把重复的ID合并起来。数字列被定义为所有相同ID的平均值(不含NAs!)。因子列被合并成一个。NA可以省略。

最后的结果应该是这样的

dfRes <- data.frame(id    = c(1, 2, 3, 4),
                    abst  = c(1, 0, 0, 3),
                    farbe = as.factor(c("keine", "keine", "keine", "rot")),
                    gier  = c(2.5, 0, 0, 3))

希望有一种方法可以快速计算,因为我有大约100万个观测值.先谢谢了!

编辑(补充)。"farbe "可能不是唯一的。在这种情况下,我认为我的数据最好的想法是有一个重复的行,但只有不同的 "farbe",所以有2个相同的ID和所有相同的,但不同的 "farbe "的值。这应该只是非常罕见的情况,但却是一个很好的补充。

在我的真实数据中,我有更多的数值和因子列。是否也可以创建一个解决方案,这样我就不必定义每一个列?

r dataframe duplicates aggregate combine
1个回答
2
投票

编辑:

刚刚看到你对非独特因素列和按类型选择列的编辑。这将是可行的,但我会想一个更干净的方法来做这件事,并向您汇报(我相信有一个简单的方法)。如果你想像原来的例子那样手动指定列,并且你有非唯一因子,只要使用 unlist()unique() 与下面的方式相同。或者,您也可以考虑将所有的因子级别合并在一行,使用 paste()collapse = "; " 或类似的东西。如果你想改变最终data.table的列顺序,可以使用 setcolorder() 在数据表上

setDT(df)

# For selecting columns later
num_cols <- sapply(df, is.numeric)
num_cols[names(num_cols) == "id"] <- FALSE
fac_cols <- sapply(df, is.factor)

df[, lapply(.SD, mean, na.rm = T), by = id, .SDcols = num_cols][
  df[, lapply(.SD, function(i) unlist(unique(i[!is.na(i)]))), by = id, .SDcols = fac_cols], on = "id"]

   id abst gier farbe
1:  1    1  2.5 keine
2:  2    0  0.0 keine
3:  3    0  0.0 keine
4:  4    3  3.0  rot2
5:  4    3  3.0   rot

它是如何工作的:它加入了数字列的摘要

df[, lapply(.SD, mean, na.rm = TRUE), by = id, .SDcols = num_cols]

与因素栏摘要

df[, lapply(.SD, function(i) unlist(unique(i[!is.na(i)]))), by = id, .SDcols = fac_cols]

编辑数据:

df <- data.frame(id    = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4),
                 abst  = c(0, NA, 2, NA, NA, NA, 0, 0, NA, 2, NA, 3, 4),
                 farbe = as.factor(c("keine", NA, "keine", NA, NA, NA, "keine", "keine", NA, NA, "rot2", "rot", "rot")),
                 gier  = c(0, NA, 5, NA, NA, NA, 0, 0, NA, 1, NA, 6, 2))

原有答复:

这里是许多人中的一个 data.table 解决方案。这将data.table按因子列排序,这样在汇总时就可以抓取最高值。我还把它转换回了一个纯粹的data.frame,但如果你不想这样做的话,就不必这样做。希望这能帮到你

另外,这是在假设 farbe 将是相同的每一个 id

library(data.table)

setDT(df)

df <- df[order(farbe), .(abst = mean(abst, na.rm = TRUE),
                         farbe = farbe[1],
                         gier = mean(gier, na.rm = TRUE)), by = id]

setDF(df)
df
  id abst farbe gier
1  1    1 keine  2.5
2  2    0 keine  0.0
3  3    0 keine  0.0
4  4    3   rot  3.0

0
投票

一个dplyr的解决方案。

library(dplyr)

df %>% 
  group_by(id) %>% 
  summarise(abst = mean(na.omit(abst)), 
            farbe = na.omit(farbe)[1],
            gier = mean(na.omit(gier)))
#> # A tibble: 4 x 4
#>      id  abst farbe  gier
#>   <dbl> <dbl> <fct> <dbl>
#> 1     1     1 keine   2.5
#> 2     2     0 keine   0  
#> 3     3     0 keine   0  
#> 4     4     3 rot     3

创建于2020-05-14,由 重读包 (v0.3.0)


0
投票

也是一个 data.table 解决办法。

    library(data.table)
    df <- data.table( # instead of data.frame
                     id    = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4), 
                     abst  = c(0, NA, 2, NA, NA, NA, 0, 0, NA, 2, NA, 3, 4),
                     farbe = as.factor(c("keine", NA, "keine", NA, NA, NA, "keine", "keine", NA, NA, NA, "rot", "rot")),
                     gier  = c(0, NA, 5, NA, NA, NA, 0, 0, NA, 1, NA, 6, 2))


    newdf <- df[,
                .(abst=mean(abst,na.rm=T), # perform mean of abst removing NAs
                  farbe=na.omit(unique(farbe)), # assuming farbe is unique for each ID, extract the unique value after removing the NAs
                  gier=mean(gier,na.rm=T)), # perform mean of gier removing NAs
                by=id] # for each ID

    newdf

       id abst farbe gier
    1:  1    1 keine  2.5
    2:  2    0 keine  0.0
    3:  3    0 keine  0.0
    4:  4    3   rot  3.0

0
投票

补充解决方案

df %>% 
  group_by(id) %>% 
  fill(farbe, .direction = "updown") %>% 
  group_by(id, farbe) %>% 
  summarise_all(~ mean(., na.rm = T))
© www.soinside.com 2019 - 2024. All rights reserved.