我想获得一个列,其中包含每个年龄段的滚动收入平均值,但要包括一岁以下的年龄段。例如,对于年龄为42和类型1的人,该类型必须使用年龄分别为41,42和43(如果有)的所有收入数据,依此类推。我想要一种系统的方法。
最小数据应如下所示:
Client Schema
我曾考虑过使用Zoo的rollapply,但这只是用于收入变量观测的顺序,而不是用于分组变量之一的值,而分组变量正是我要“滚动”的变量。
按income <- c(1000, 2000, 3000, 4000, 6000, 7000, 8000, 9000, 10000, 11000)
age <- c(41, 42, 42, 44, 45, 46, 47, 47, 49, 50)
type <- c(1,1,2,2,1,2,1,2,1,1)
df <- as.data.frame(cbind(income, age, type))
排序,但以滚动方式将年龄分组(年龄1,年龄,年龄+1)。目的是使年龄的平均收入每三年重叠一次。当然,在年龄分布的尾部的两个年龄段的收入都将减少或根本没有增加。
谢谢!
P.S。我认为,预期结果将是这样(手动计算):
dplyr (group_by(type,age)) %>% summarize (avg=mean(income))
请注意,如果(年龄)和类型的每个(滚动)年龄的平均收入只有该年龄的所有三年中所有类型的收入都具有NA。 即使给定年龄的实际数据是NA,但如果观测值低于或低于该值,则将计算平均值(忽略NA)。
答案 0 :(得分:1)
这是一种蛮力的tidyverse
方法。
library(tidyverse)
df <- data.frame(income = c(1000, 2000, 3000, 4000, 6000, 7000, 8000, 9000, 10000, 11000),
age = c(41, 42, 42, 44, 45, 46, 47, 47, 49, 50),
type = c(1,1,2,2,1,2,1,2,1,1))
指定每个滚动平均值中包含的年份,这里的意思是“包括上一年,下一年和下一年。”
yr_range = c(-1:1) # same as c(-1, 0, 1)
使用yr_range
为tidyr::uncount
中的每个条目复制每一行,然后创建一个虚拟age_adj
来调整每一行的年龄以将其移动到存储桶中以进行汇总:>
df2 <- df %>%
uncount(length(yr_range)) %>%
mutate(age_adj = rep(yr_range, length.out = n()),
age_bucket = age + age_adj) %>%
# At this point it looks like:
# income age type age_adj age_bucket
#1 1000 41 1 -1 40
#2 1000 41 1 0 41
#3 1000 41 1 1 42
#4 2000 42 2 -1 41
#5 2000 42 2 0 42
#6 2000 42 2 1 43
group_by(type, age_bucket) %>%
summarize(income_mean = mean(income)) %>%
# optional, to prune edge years beyond orig data
filter(age_bucket >= min(df$age),
age_bucket <= max(df$age))
> df2
# A tibble: 18 x 3
# Groups: type [2]
type age_bucket income_mean
<dbl> <dbl> <dbl>
1 1 41 1500
2 1 42 1500
3 1 43 2000
4 1 44 6000
5 1 45 6000
6 1 46 7000
7 1 47 8000
8 1 48 9000
9 1 49 10500
10 1 50 10500
11 2 41 3000
12 2 42 3000
13 2 43 3500
14 2 44 4000
15 2 45 5500
16 2 46 8000
17 2 47 8000
18 2 48 9000
答案 1 :(得分:1)
创建类型/年龄网格<ItemsControl x:Class="Miotec.PressureMapping.UserControls.BaroLayerContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Miotec.PressureMapping.UserControls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<ItemsControl.Resources>
<Style TargetType="local:BaroLayerContainer">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas Width="{Binding Parametros.Colunas}"
Height="{Binding Parametros.Linhas}"
IsItemsHost="True"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Resources>
<Viewbox Stretch="Uniform" x:Name="container">
<ItemsPresenter
Width="{Binding ActualWidth, ElementName=container}"
Height="{Binding ActualHeight, ElementName=container}"/>
</Viewbox>
</ItemsControl>
并将其与g
合并,得到df
。然后使用m
通过ave
运行rollapply
:
type
给予:
library(zoo)
g <- expand.grid(type = unique(df$type), age = seq(min(df$age), max(df$age)))
m <- merge(g, df, all.x = TRUE)
roll <- function(x) rollapply(x, 3, mean, na.rm = TRUE, partial = TRUE)
transform(m, avg = ave(income, type, FUN = roll))