R按ID将重复行与数据帧中的不同列类型组合在一起

R按ID将重复行与数据帧中的不同列类型组合在一起,r,dataframe,data.table,aggregate,tidyverse,R,Dataframe,Data.table,Aggregate,Tidyverse,我有一个以列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, N

我有一个以列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))
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))
dfdplyr解决方案

库(dplyr)
df%>%
分组依据(id)%>%
总结(Abs=平均值(不适用,省略(Abs)),
farbe=na.省略(farbe)[1],
gier=平均值(不包含(gier)))
#>#tibble:4 x 4
#>我是法比·吉尔
#>      
#>1基恩2.5
#>2 2 0基恩0
#>330基恩0
#>4 4 3腐烂3
由(v0.3.0)dplyr解决方案于2020年5月14日创建

库(dplyr)
df%>%
分组依据(id)%>%
总结(Abs=平均值(不适用,省略(Abs)),
farbe=na.省略(farbe)[1],
gier=平均值(不包含(gier)))
#>#tibble:4 x 4
#>我是法比·吉尔
#>      
#>1基恩2.5
#>2 2 0基恩0
#>330基恩0
#>4 4 3腐烂3

由(v0.3.0)于2020年5月14日创建,也是一个
数据。表
解决方案:

    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
库(data.table)

df也是一个
数据。表
解决方案:

    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
库(data.table)
df编辑

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))
刚才看到了关于非唯一因子列和按类型选择列的编辑。这将起作用,但我会考虑一个更干净的方法来做这件事,并报告回来(我相信有一个简单的方法)。如果要像原始示例那样手动指定列,并且有非唯一因子,只需使用
unlist()
unique()
以与下面相同的方式。或者,您可以考虑将一行中的所有因子级别组合为<代码> PASTEE()/<代码> <代码>塌陷=“;”或类似的效果。如果要更改final data.table的列顺序,请在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))
编辑

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))
刚才看到了关于非唯一因子列和按类型选择列的编辑。这将起作用,但我会考虑一个更干净的方法来做这件事,并报告回来(我相信有一个简单的方法)。如果要像原始示例那样手动指定列,并且有非唯一因子,只需使用
unlist()
unique()
以与下面相同的方式。或者,您可以考虑将一行中的所有因子级别组合为<代码> PASTEE()/<代码> <代码>塌陷=“;”或类似的效果。如果要更改final data.table的列顺序,请在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))
附加解决方案

df %>% 
  group_by(id) %>% 
  fill(farbe, .direction = "updown") %>% 
  group_by(id, farbe) %>% 
  summarise_all(~ mean(., na.rm = T))
附加解决方案

df %>% 
  group_by(id) %>% 
  fill(farbe, .direction = "updown") %>% 
  group_by(id, farbe) %>% 
  summarise_all(~ mean(., na.rm = T))


对于相同的
id
farbe
是否总是相同的?好问题,我希望如此。否则问题就没那么大了。但是必须做出决定,应该使用哪一个值。我认为目前发布的所有解决方案都假定farbe是唯一的(至少我的是唯一的)。如果不是,你是唯一知道如何处理不同价值观的人。然后我们可以修改答案。你是对的。在这种情况下,我认为对我的数据来说最好的办法是有一个重复的行,但只使用不同的“farbe”。这应该是非常罕见的情况,没关系。
farbe
对于同一个
id
是否总是一样的?好问题,我希望如此。否则问题就没那么大了。但是必须做出决定,应该使用哪一个值。我认为目前发布的所有解决方案都假定farbe是唯一的(至少我的是唯一的)。如果不是,你是唯一知道如何处理不同价值观的人。然后我们可以修改答案。你是对的。在这种情况下,我认为对我的数据来说最好的办法是有一个重复的行,但只使用不同的“farbe”。这应该是非常罕见的情况,这很好。很好的解决方案。如果我有很多数值列和因子列,如何实现这一点?我必须定义每一列吗?我在我的数据上尝试了这个解决方案,使用了大约1百万次的观察。这需要超过10分钟!为什么呢?我尝试了data.table解决方案,花了大约1秒的时间。很好的解决方案。如果我有很多数值列和因子列,如何实现这一点?我必须定义每一列吗?我在我的数据上尝试了这个解决方案,使用了大约1百万次的观察。这需要超过10分钟!为什么呢?我尝试了data.table解决方案,花了大约1秒的时间。为什么data.table解决方案比dplyr解决方案(超过10分钟!)快这么多(大约1秒,用于百万次观测)?是否可以对所有数值列和系数列执行此操作?我有更多的列,所以不定义每一个列会更容易。有没有办法移除NAN?(不是NAs)嘿@Bolle,希望编辑有帮助。不是100%确定你对NaN的意思——你必须发布更多的数据或其他问题。我猜这是因为你取的是只有
NA
值的组的平均值(即
平均值(c(NA,NA),NA.rm=T)
)。另外,
dplyr
解决方案速度较慢的主要原因可能是它在分组后为每一列调用了
na.omit()
。“你的新解决方案看起来不错。我测试了一个包含更多列的datatable。它是有效的,但我得到一个警告:“组32133的j结果的第1项长度为零。这将填充2个NAs以匹配此结果中最长的列。”这是一个大问题吗?这到底意味着什么?我如何解决这个问题?嘿@Bolle,没有看到数据,我真的不知道。我会通过使用
.GRP
添加索引手动检查组,并查看发生了什么。前/后摘要。希望这有帮助!我喜欢你的解决方案,它很好阅读和理解。如果我告诉你这是一个时间序列,会有区别吗