R按ID将重复行与数据帧中的不同列类型组合在一起
我有一个以列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
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
添加索引手动检查组,并查看发生了什么。前/后摘要。希望这有帮助!我喜欢你的解决方案,它很好阅读和理解。如果我告诉你这是一个时间序列,会有区别吗