我有一个由两部分组成的问题。我已经搜遍了所有的堆栈并找到了与我的问题相关的答案,但我尝试过没有任何变化。在此先感谢您的帮助!
我有一个包含许多变量的大型数据框。
首先,我想(1)通过另一个变量(在我的情况下,扬声器)标准化变量,以及(2)在变量标准化后过滤掉值(大于2个标准)偏离平均值的偏差)。 (1)和(2)可以通过使用dplyr的函数来处理。
第二,我想要为此做很多变量,所以我试图找到一种自动执行此操作的方法,例如使用for循环。
问题1:编写包含dplyr函数的函数
以下是我的数据框的示例:
df = data.frame(speaker=c("eng1","eng1","eng1","eng1","eng1","eng1","eng2","eng2","eng2","eng2","eng2"),
ratio_means001=c(0.56,0.202,0.695,0.436,0.342,10.1,0.257,0.123,0.432,0.496,0.832),
ratio_means002=c(0.66,0.203,0.943,0.432,0.345,0.439,0.154,0.234,NA,0.932,0.854))
输出:
speaker ratio_means001 ratio_means002
1 eng1 0.560 0.660
2 eng1 0.202 0.203
3 eng1 0.695 0.943
4 eng1 0.436 0.432
5 eng1 0.342 0.345
6 eng1 10.100 0.439
7 eng2 0.257 0.154
8 eng2 0.123 0.234
9 eng2 0.432 NA
10 eng2 0.496 0.932
11 eng2 0.832 0.854
以下是我想要变成函数的基本代码:
standardized_data = group_by(df, speaker) %>%
mutate(zRatio1 = as.numeric(scale(ratio_means001)))%>%
filter(!abs(zRatio1) > 2)
这样数据框现在看起来像这样(例如):
speaker ratio_means001 ratio_means002 zRatio1
(fctr) (dbl) (dbl) (dbl)
1 eng1 0.560 0.660 -0.3792191
2 eng1 0.202 0.203 -0.4699781
3 eng1 0.695 0.943 -0.3449943
4 eng1 0.436 0.432 -0.4106552
5 eng1 0.342 0.345 -0.4344858
6 eng2 0.257 0.154 -0.6349445
7 eng2 0.123 0.234 -1.1325034
8 eng2 0.432 NA 0.0148525
9 eng2 0.496 0.932 0.2524926
10 eng2 0.832 0.854 1.5001028
到目前为止,这是我的功能。 mutate部分有效,但我一直在努力添加过滤器部分:
library(lazyeval)
standardize_variable = function(col1, new_col_name) {
mutate_call = lazyeval::interp(b = interp(~ scale(a)), a = as.name(col1))
group_by(data,speaker) %>%
mutate_(.dots = setNames(list(mutate_call), new_col_name)) %>%
filter_(interp(~ !abs(b) > 2.5, b = as.name(new_col_name))) # this part does not work
}
当我尝试运行该函数时收到以下错误:
data = standardize_variable("ratio_means001","zRatio1")
Error in substitute_(`_obj`[[2]], values) :
argument "_obj" is missing, with no default
问题2:循环使用功能
我想将上述函数应用到很多变量中,所以我想找到一种方法来使用循环或其他有用的函数来帮助自动执行此过程。变量名在最后只有一个数字不同,所以我想出了类似的东西:
d <- data.frame()
for(i in 1:2)
{
col1 <- paste("ratio_means00", i, sep = "")
new_col <- paste("zRatio", i, sep = "")
d <- rbind(d, standardize_variable(col1, new_col))
}
但是,我收到以下错误:
Error in match.names(clabs, names(xi)) :
names do not match previous names
再次感谢您对这些问题的任何帮助!
答案 0 :(得分:0)
备选方案1
我相信你使用函数时遇到的主要问题与你调用interp
两次有关。修复导致filter
的其他问题,我认为这是由于scale
添加了属性(我使用的是开发版 dplyr ,dplyr_0.4.3.9001) 。在as.numeric
周围包裹scale
可以摆脱它。
所以修复后你的功能如下:
standardize_variable = function(col1, new_col_name) {
mutate_call = lazyeval::interp(~as.numeric(scale(a)), a = as.name(col1))
group_by(df, speaker) %>%
mutate_(.dots = setNames(list(mutate_call), new_col_name)) %>%
filter_(interp(~ !abs(b) > 2, b = as.name(new_col_name)))
}
我发现变量的循环比你的变量要复杂得多,因为我相信你想要为每个变量创建一个数据集后将它们合并在一起。一种选择是将它们保存到列表中,然后使用do.call
和merge
来获取最终数据集。
d = list()
for(i in 1:2) {
col1 <- paste("ratio_means00", i, sep = "")
new_col <- paste("zRatio", i, sep = "")
d[[i]] = standardize_variable(col1, new_col)
}
do.call(merge, d)
speaker ratio_means001 ratio_means002 zRatio1 zRatio2
1 eng1 0.202 0.203 -0.4699781 -1.1490444
2 eng1 0.342 0.345 -0.4344858 -0.6063693
3 eng1 0.436 0.432 -0.4106552 -0.2738853
4 eng1 0.560 0.660 -0.3792191 0.5974521
5 eng1 0.695 0.943 -0.3449943 1.6789806
6 eng2 0.123 0.234 -1.1325034 -0.7620572
7 eng2 0.257 0.154 -0.6349445 -0.9590348
8 eng2 0.496 0.932 0.2524926 0.9565726
9 eng2 0.832 0.854 1.5001028 0.7645194
备选方案2
替代所有这一切的方法是在问题的第一部分使用mutate_each
和rename_
,然后使用带有interp
循环的lapply
同时对所有缩放变量进行最终过滤。
在下面的代码中,我利用mutate_each
允许从 dplyr_0.4.3.9001 开始为单个函数命名的事实。在rename_
中,事情看起来有点复杂,因为我正在为新列创建您想要的名称。要简化一些事情,您可以将它们从_z
mutate_each
结束,并使用rename_
和gsub
保存grepl
的复杂步骤。
df2 = df %>%
group_by(speaker) %>%
mutate_each(funs(z = as.numeric(scale(.))), starts_with("ratio_means00")) %>%
rename_(.dots = setNames(names(.)[grepl("z", names(.))],
paste0("zR", gsub("r|_z|_means00", "", names(.)[grepl("z", names(.))]))))
完成后,您只需按多列进行过滤即可。我认为最简单的方法是使用interp
和lapply
制作要过滤的条件列表,然后将其添加到.dots
的{{1}}参数中。
filter_
备选方案3
如果我重塑数据集而不是跨列工作,我经常发现这些问题最为直接。例如,仍然使用最新版本的dots = lapply(names(df2)[starts_with("z", vars = names(df2))],
function(y) interp(~abs(x) < 2, x = as.name(y)))
filter_(df2, .dots = dots)
Source: local data frame [9 x 5]
Groups: speaker [2]
speaker ratio_means001 ratio_means002 zRatio1 zRatio2
(fctr) (dbl) (dbl) (dbl) (dbl)
1 eng1 0.560 0.660 -0.3792191 0.5974521
2 eng1 0.202 0.203 -0.4699781 -1.1490444
3 eng1 0.695 0.943 -0.3449943 1.6789806
4 eng1 0.436 0.432 -0.4106552 -0.2738853
5 eng1 0.342 0.345 -0.4344858 -0.6063693
6 eng2 0.257 0.154 -0.6349445 -0.9590348
7 eng2 0.123 0.234 -1.1325034 -0.7620572
8 eng2 0.496 0.932 0.2524926 0.9565726
9 eng2 0.832 0.854 1.5001028 0.7645194
但跳过重命名步骤以简化您可以使用 tidyr 中的mutate_each
函数gather
将所有标准化列组合在一起然后gather
新列。
filter
如果所需的最终表单是宽格式,您可以使用library(tidyr)
df %>%
group_by(speaker) %>%
mutate_each(funs(z = as.numeric(scale(.))), starts_with("ratio_means00")) %>%
gather(group, zval, ends_with("_z")) %>%
filter(abs(zval) <2 )
# First 12 lines of output
Source: local data frame [20 x 5]
Groups: speaker [2]
speaker ratio_means001 ratio_means002 group zval
<fctr> <dbl> <dbl> <chr> <dbl>
1 eng1 0.560 0.660 ratio_means001_z -0.3792191
2 eng1 0.202 0.203 ratio_means001_z -0.4699781
3 eng1 0.695 0.943 ratio_means001_z -0.3449943
4 eng1 0.436 0.432 ratio_means001_z -0.4106552
5 eng1 0.342 0.345 ratio_means001_z -0.4344858
6 eng2 0.257 0.154 ratio_means001_z -0.6349445
7 eng2 0.123 0.234 ratio_means001_z -1.1325034
8 eng2 0.432 NA ratio_means001_z 0.0148525
9 eng2 0.496 0.932 ratio_means001_z 0.2524926
10 eng2 0.832 0.854 ratio_means001_z 1.5001028
11 eng1 0.560 0.660 ratio_means002_z 0.5974521
12 eng1 0.202 0.203 ratio_means002_z -1.1490444
...
(也来自 tidyr 。对我而言,一个优点是您可以保留所有值即使另一个变量未通过过滤步骤,也会变量。
spread
如果您不想保留df %>%
group_by(speaker) %>%
mutate_each(funs(z = as.numeric(scale(.))), starts_with("ratio_means00")) %>%
gather(group, zval, ends_with("_z")) %>%
filter(abs(zval) <2 ) %>%
spread(group, zval)
Source: local data frame [11 x 5]
Groups: speaker [2]
speaker ratio_means001 ratio_means002 ratio_means001_z ratio_means002_z
<fctr> <dbl> <dbl> <dbl> <dbl>
1 eng1 0.202 0.203 -0.4699781 -1.1490444
2 eng1 0.342 0.345 -0.4344858 -0.6063693
3 eng1 0.436 0.432 -0.4106552 -0.2738853
4 eng1 0.560 0.660 -0.3792191 0.5974521
5 eng1 0.695 0.943 -0.3449943 1.6789806
6 eng1 10.100 0.439 NA -0.2471337
7 eng2 0.123 0.234 -1.1325034 -0.7620572
8 eng2 0.257 0.154 -0.6349445 -0.9590348
9 eng2 0.432 NA 0.0148525 NA
10 eng2 0.496 0.932 0.2524926 0.9565726
11 eng2 0.832 0.854 1.5001028 0.7645194
,可以在以后随时NA
。