使用dplyr将数据帧列重新缩放为基线条目的百分比
我经常需要相对于某个基线时间的值(通常为基线的百分比)重新调整时间序列。这里有一个例子使用dplyr将数据帧列重新缩放为基线条目的百分比,r,dplyr,R,Dplyr,我经常需要相对于某个基线时间的值(通常为基线的百分比)重新调整时间序列。这里有一个例子 > library(dplyr) > library(magrittr) > library(tibble) > library(tidyr) # [messages from package imports snipped] > set.seed(42) > mexico <- tibble(Year=2000:2004, Country='Mexico', A=1
> library(dplyr)
> library(magrittr)
> library(tibble)
> library(tidyr)
# [messages from package imports snipped]
> set.seed(42)
> mexico <- tibble(Year=2000:2004, Country='Mexico', A=10:14+rnorm(5), B=20:24+rnorm(5))
> usa <- tibble(Year=2000:2004, Country='USA', A=30:34+rnorm(5), B=40:44+rnorm(5))
> table <- rbind(mexico, usa)
> table
# A tibble: 10 x 4
Year Country A B
<int> <chr> <dbl> <dbl>
1 2000 Mexico 11.4 19.9
2 2001 Mexico 10.4 22.5
3 2002 Mexico 12.4 21.9
4 2003 Mexico 13.6 25.0
5 2004 Mexico 14.4 23.9
6 2000 USA 31.3 40.6
7 2001 USA 33.3 40.7
8 2002 USA 30.6 39.3
9 2003 USA 32.7 40.6
10 2004 USA 33.9 45.3
我的第二次尝试是使用transform
,但这失败了,因为transform
似乎无法识别dplyr
组,即使它起作用,也是次优的,因为它要求我知道2001年是时间序列中的第二年
> table %>%
arrange(Country, Year) %>%
gather(variable, value, -Year, -Country) %>%
group_by(Country, variable) %>%
transform(norm=value*100/value[2])
Year Country variable value norm
1 2000 Mexico A 11.37096 108.9663
2 2001 Mexico A 10.43530 100.0000
3 2002 Mexico A 12.36313 118.4741
4 2003 Mexico A 13.63286 130.6418
5 2004 Mexico A 14.40427 138.0340
6 2000 USA A 31.30487 299.9901
7 2001 USA A 33.28665 318.9811
8 2002 USA A 30.61114 293.3422
9 2003 USA A 32.72121 313.5627
10 2004 USA A 33.86668 324.5395
11 2000 Mexico B 19.89388 190.6402
12 2001 Mexico B 22.51152 215.7247
13 2002 Mexico B 21.90534 209.9157
14 2003 Mexico B 25.01842 239.7480
15 2004 Mexico B 23.93729 229.3876
16 2000 USA B 40.63595 389.4085
17 2001 USA B 40.71575 390.1732
18 2002 USA B 39.34354 377.0235
19 2003 USA B 40.55953 388.6762
20 2004 USA B 45.32011 434.2961
这将是一个更好的扩展,但这里有一个简单的解决方案。你可以参考
A[Year==2001]
内的mutate
,就像你可能在R基中做的table$A[table$Year==2001]
一样。这让你可以根据2001年的基线或你可能需要的任何其他年份进行缩放
编辑:我丢失了一个组_by
,以确保仅根据组中的其他值对值进行缩放。“健全性检查”(我显然没有这样做)是指2001年墨西哥的值应该有一个1的标度值,美国和其他任何国家也是如此
库(tidyverse)
种子(42)
墨西哥#西藏:10 x 6
#>#群体:国家[2]
#>年份国家A B A_基地2001 B_基地2001
#>
#>1 2000墨西哥11.4 19.9 1.09 0.884
#>2 2001墨西哥10.4 22.5 1
#>3 2002年墨西哥12.4 21.9 1.18 0.973
#>4 2003年墨西哥13.6 25.0 1.31 1.11
#>5 2004年墨西哥14.4 23.9 1.38 1.06
#>6 2000美国31.3 40.6 0.940 0.998
#>7 2001美国33.3 40.7 1
#>8 2002美国30.6 39.3 0.920 0.966
#>9 2003美国32.7 40.6 0.983 0.996
#>10 2004美国33.9 45.3 1.02 1.11
由(v0.2.0)于2018年5月23日创建。受卡米尔答案的启发,我发现了一种简单的方法,可以很好地扩展:
table %>%
gather(variable, value, -Year, -Country) %>%
group_by(Country, variable) %>%
mutate(value=100*value/value[Year == 2001]) %>%
spread(variable, value)
# A tibble: 10 x 4
# Groups: Country [2]
Year Country A B
<int> <chr> <dbl> <dbl>
1 2000 Mexico 109. 88.4
2 2000 USA 94.0 99.8
3 2001 Mexico 100. 100
4 2001 USA 100 100
5 2002 Mexico 118. 97.3
6 2002 USA 92.0 96.6
7 2003 Mexico 131. 111.
8 2003 USA 98.3 99.6
9 2004 Mexico 138. 106.
10 2004 USA 102. 111.
第二种等效方法是创建一个新表,其中列按比例“就地”缩放,然后将其与原始表合并
table %>%
gather(variable, value, -Year, -Country) %>%
group_by(Country, variable) %>%
mutate(value=100*value/value[Year == 2001]) %>%
ungroup() %>%
mutate(variable=paste(variable, 'scaled', sep='_')) %>%
spread(variable, value) %>%
inner_join(table)
Joining, by = c("Year", "Country")
# A tibble: 10 x 6
Year Country A_scaled B_scaled A B
<int> <chr> <dbl> <dbl> <dbl> <dbl>
1 2000 Mexico 109. 88.4 11.4 19.9
2 2000 USA 94.0 99.8 31.3 40.6
3 2001 Mexico 100. 100 10.4 22.5
4 2001 USA 100 100 33.3 40.7
5 2002 Mexico 118. 97.3 12.4 21.9
6 2002 USA 92.0 96.6 30.6 39.3
7 2003 Mexico 131. 111. 13.6 25.0
8 2003 USA 98.3 99.6 32.7 40.6
9 2004 Mexico 138. 106. 14.4 23.9
10 2004 USA 102. 111. 33.9 45.3
表%>%
聚集(变量、值、-年、-国家)%>%
集团单位(国家,变量)%>%
变异(值=100*值/值[年==2001])%>%
解组()%>%
变异(变量=粘贴(变量,'缩放',sep='')%>%
价差(变量、值)%>%
内螺纹联接(表)
加入,由=c(“年度”、“国家”)
#一个tibble:10x6
年份国家A_标B_标A B
1 2000年墨西哥109。88.4 11.4 19.9
2 2000美国94.0 99.8 31.3 40.6
3 2001年墨西哥100。100 10.4 22.5
4 2001美国100 100 33.3 40.7
5 2002年墨西哥118。97.3 12.4 21.9
6 2002美国92.0 96.6 30.6 39.3
7 2003年墨西哥131。11113.6 25.0
8 2003美国98.3 99.6 32.7 40.6
9 2004年墨西哥138。10614.4 23.9
10 2004年美国102。11133.9 45.3
可以将最终的
内部联接
替换为排列(县,年)%%>%select(-Country,-Year)%%>%bind\u cols(表)
,这可能对某些数据集的性能更好,尽管它对列的排序不太理想。在A_base2001
和B_base2001
下的2001
条目不应该都是1
?我认为问题在于两个基线向量的长度(例如c(10.4,33.3)
对于A
)按照给定的顺序循环使用A
:墨西哥2000对墨西哥基线,墨西哥2001对美国基线,然后墨西哥2002对墨西哥基线,等等。添加一个arrange(year)
通过对齐几对年份条目来解决这个问题,但是如果缺少任何年份/国家组合(实际数据中经常出现),那么它也很脆弱。老实说,这是一个足够常见的问题,值得编写一个dplyr
扩展包来解决吗?@ConnorHarris yes,我不知道我怎么会错过那个!通过添加一个group\u可以解决这一问题,因此墨西哥的价值观只会相互对比,美国也是如此。我现在正在解决这一问题。@ConnorHarris至少在我的工作领域,即分析人口统计和其他普查数据,这是一项非常常见的任务,通常需要我进行大量的收集
/传播
争论。实际上,我现在正在编写一个软件包,使用一个函数来简化和扩展这个过程。我想我找到了一种不需要指定列名的工作方法。
table %>%
gather(variable, original, -Year, -Country) %>%
group_by(Country, variable) %>%
mutate(scaled=100*original/original[Year == 2001]) %>%
gather(scaled, value, -Year, -Country, -variable) %>%
unite(variable_scaled, variable, scaled, sep='_') %>%
mutate(variable_scaled=gsub("_original", "", variable_scaled)) %>%
spread(variable_scaled, value)
# A tibble: 10 x 6
# Groups: Country [2]
Year Country A A_scaled B B_scaled
<int> <chr> <dbl> <dbl> <dbl> <dbl>
1 2000 Mexico 11.4 109. 19.9 88.4
2 2000 USA 31.3 94.0 40.6 99.8
3 2001 Mexico 10.4 100. 22.5 100
4 2001 USA 33.3 100 40.7 100
5 2002 Mexico 12.4 118. 21.9 97.3
6 2002 USA 30.6 92.0 39.3 96.6
7 2003 Mexico 13.6 131. 25.0 111.
8 2003 USA 32.7 98.3 40.6 99.6
9 2004 Mexico 14.4 138. 23.9 106.
10 2004 USA 33.9 102. 45.3 111.
table %>%
gather(variable, value, -Year, -Country) %>%
group_by(Country, variable) %>%
mutate(value=100*value/value[Year == 2001]) %>%
ungroup() %>%
mutate(variable=paste(variable, 'scaled', sep='_')) %>%
spread(variable, value) %>%
inner_join(table)
Joining, by = c("Year", "Country")
# A tibble: 10 x 6
Year Country A_scaled B_scaled A B
<int> <chr> <dbl> <dbl> <dbl> <dbl>
1 2000 Mexico 109. 88.4 11.4 19.9
2 2000 USA 94.0 99.8 31.3 40.6
3 2001 Mexico 100. 100 10.4 22.5
4 2001 USA 100 100 33.3 40.7
5 2002 Mexico 118. 97.3 12.4 21.9
6 2002 USA 92.0 96.6 30.6 39.3
7 2003 Mexico 131. 111. 13.6 25.0
8 2003 USA 98.3 99.6 32.7 40.6
9 2004 Mexico 138. 106. 14.4 23.9
10 2004 USA 102. 111. 33.9 45.3