如何根据另一个数据框中的值计算一个数据框中的值
How to calculate values in one dataframe based on the values in another dataframe
我有一个包含多个不同分析的数据框,每个分析都包含多行数据。我只想计算每次分析中几行的平均值,这些行因分析而异。有一个数据框包含分析,另一个数据框包含每个分析的平均值所需的开始和结束行号。下面是一个简单的例子。
分析
df1 <- structure(list(analysis = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L),
line = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L),
value = c(4.8, 9.8, 7.1, 7.4, 7.4, 3.3, 4.5, 8.7, 3.9, 3.6, 1.9, 9.4, 0.9, 0.6, 2.1, 6.1, 5.3, 4.7, 9.7, 8.6, 8.9, 3.4, 8.7, 7.1)),
class = "data.frame", row.names = c(NA, -24L))
开始和结束的行号,我想要每个分析的平均值:
df2 <- structure(list(analysis = 1:3,
startnum = c(3L, 3L, 2L),
endnum = c(7L, 6L, 4L)),
class = "data.frame", row.names = c(NA, -3L))
我设想生成的数据框是这样的:
structure(list(analysis=1:3,
avgval=c(5.94, 3.2, 7.67)),
class = "data.frame", row.names = c(NA, -3L))
我相信 'apply' 家庭的答案很简单,但不知道如何做到这一点。我可以将数据帧转换为 'lapply' 的列表,但不确定如何继续。
非常感谢,
-R
这是使用data.table
的方法
library(data.table)
setDT(df1)
setDT(df2)
在 df2
中按组从 startnum
到 endnum
的序列创建一个 line
列。
df2 <- df2[, .(line = seq(startnum, endnum)), by = analysis]
加入两个 data.tables 并按组聚合。
out <- df1[df2, on = c("analysis", "line")]
out <- out[, .(avgval = mean(value)), by = analysis]
out
# analysis avgval
#1: 1 5.940000
#2: 2 3.200000
#3: 3 7.666667
如果您想继续data.frame
,请致电setDF(out)
。
希望对您有所帮助。
在tidyverse
你可以做:
df1 %>%
left_join(df2, by = c("analysis" = "analysis")) %>% #Merging df1 with df2
group_by(analysis) %>% #Grouping by "analysis"
summarise(avgval = mean(value[line >= startnum & line <= endnum])) #Calculating the mean based on given conditions
analysis avgval
<int> <dbl>
1 1 5.94
2 2 3.20
3 3 7.67
我有一个包含多个不同分析的数据框,每个分析都包含多行数据。我只想计算每次分析中几行的平均值,这些行因分析而异。有一个数据框包含分析,另一个数据框包含每个分析的平均值所需的开始和结束行号。下面是一个简单的例子。
分析
df1 <- structure(list(analysis = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L),
line = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L),
value = c(4.8, 9.8, 7.1, 7.4, 7.4, 3.3, 4.5, 8.7, 3.9, 3.6, 1.9, 9.4, 0.9, 0.6, 2.1, 6.1, 5.3, 4.7, 9.7, 8.6, 8.9, 3.4, 8.7, 7.1)),
class = "data.frame", row.names = c(NA, -24L))
开始和结束的行号,我想要每个分析的平均值:
df2 <- structure(list(analysis = 1:3,
startnum = c(3L, 3L, 2L),
endnum = c(7L, 6L, 4L)),
class = "data.frame", row.names = c(NA, -3L))
我设想生成的数据框是这样的:
structure(list(analysis=1:3,
avgval=c(5.94, 3.2, 7.67)),
class = "data.frame", row.names = c(NA, -3L))
我相信 'apply' 家庭的答案很简单,但不知道如何做到这一点。我可以将数据帧转换为 'lapply' 的列表,但不确定如何继续。
非常感谢, -R
这是使用data.table
library(data.table)
setDT(df1)
setDT(df2)
在 df2
中按组从 startnum
到 endnum
的序列创建一个 line
列。
df2 <- df2[, .(line = seq(startnum, endnum)), by = analysis]
加入两个 data.tables 并按组聚合。
out <- df1[df2, on = c("analysis", "line")]
out <- out[, .(avgval = mean(value)), by = analysis]
out
# analysis avgval
#1: 1 5.940000
#2: 2 3.200000
#3: 3 7.666667
如果您想继续data.frame
,请致电setDF(out)
。
希望对您有所帮助。
在tidyverse
你可以做:
df1 %>%
left_join(df2, by = c("analysis" = "analysis")) %>% #Merging df1 with df2
group_by(analysis) %>% #Grouping by "analysis"
summarise(avgval = mean(value[line >= startnum & line <= endnum])) #Calculating the mean based on given conditions
analysis avgval
<int> <dbl>
1 1 5.94
2 2 3.20
3 3 7.67