是只有一个不同名称的ID。为了检测它们,我建立了这个功能:
ddply(my_dataframe, ~ID_col, summarise, number_of_names = length(unique(names_col)))
这很好用,所以我在第一个col中得到一个ID,在第二个col中有一些不同的名字。
因为我需要对几个ID /名称对执行此操作,所以我决定将ddply函数放在函数中。我这样做了:
function_name = function (source, id, name) {
ddply(source, ~id, summarise, number_of_names = length(unique(name)))
不幸的是,当我使用它时会抛出错误:
function_name(my_dataframe, ID_col, names_col)
# Error in unique.default(x) : unique() applies only to vectors
正如您所看到的,它与之前的代码完全相同,但嵌入了具有三个变量的函数中。我迫不及待地想要修复它并真正期待解决方案。
供参考: 在我的原始代码中,我没有使用" source"或"名称"但是德语单词,所以现有的其他功能应该没有问题。我也已经尝试将变量放在引号中。
感谢您的帮助!
这就是DF有点像:
my_dataframe <- data.frame(
ID_col = c(letters[2:9], letters[3:4]),
names_col = paste0("name-", letters[1:10])
)
有303个ID,但有963个名字。
答案 0 :(得分:6)
R始终具有通过使用双方括号按变量名的值选择列的功能。使用import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.core.AnyOf.anyOf;
...
Date expectedMin = new Date()
// Execute the method being tested
Date resultDate = getDate();
// Validate
assertThat(resultDate, anyOf(greaterThan(expectedMin), equalTo(expectedMin)))
,你可以这样做:
tapply
然后:
function_name = function (source, id, name) {
data.frame(
N=tapply(
source[[name]],
my_dataframe[[id]],
function(x){
length(unique(x))
}
)
)
}
请注意,名称位于返回数据框的行名称中。
答案 1 :(得分:2)
1)eval / substitute 将身体包裹在eval.parent(替换(...))中以使参数被替换。下面的ddply(...)
行与那个问题。
library(plyr)
function_name = function (source, id, name) eval.parent(substitute(
ddply(source, ~id, summarise, number_of_names = length(unique(name)))
))
function_name(my_dataframe, ID_col, names_col)
2)替换这也有效,不依赖于eval
:
function_name = function (source, id, name) {
id <- substitute(id)
name <- deparse(substitute(name))
ddply(source, id, function(x) summarise(x, number_of_names = length(unique(x[[name]]))))
}
function_name(my_dataframe, ID_col, names_col)
2a)传递字符串如果你愿意传递字符串,可以将它缩短为与(2)相同,除非我们省略了正文的前两行并且我们传递了字符调用它时的字符串:
function_name = function (source, id, name) {
ddply(source, id, function(x) summarise(x, number_of_names = length(unique(x[[name]]))))
}
function_name(my_dataframe, "ID_col", "names_col")
3)defmacro 另一种方法是使用gtools中的defmacro
创建宏。 ddply(...)
电话与问题中的电话相同。
library(gtools)
macro_name <- defmacro(source, id, name, expr =
ddply(source, ~id, summarise, number_of_names = length(unique(name)))
)
macro_name(my_dataframe, ID_col,names_col)
答案 2 :(得分:0)
我们可以使用quosure
中的dplyr
来执行此操作。 enquo
获取输入变量,转换为quosure
,在group_by
,summarise
内,我们取消引用(UQ
)quosure进行评估
library(dplyr)
f1 <- function(source, id, name) {
id <- enquo(id)
name <- enquo(name)
source %>%
group_by(UQ(id)) %>%
summarise(number_of_names = n_distinct(UQ(name)))
}
f1(my_dataframe, ID_col, names_col)
# A tibble: 3 x 2
# ID_col number_of_names
# <chr> <int>
#1 FU181 2
#2 FU901 1
#3 FU992 1
注意:解决方案基于dplyr
,plyr
是%>%
的更高级版本。该解决方案将输入参数视为未引用的,并且还可以修改它以使用带引号的参数。解决方案可以使用管道(tidyverse
)进行扩展,并且非常灵活
注意2:我们没有发现lazyeval
变得更加混乱,但实际上与以前使用my_dataframe <- structure(list(ID_col = c("FU901", "FU992", "FU181", "FU181"),
names_col = c("take a breath", "use a tissue", "get up",
"getting up")), .Names = c("ID_col", "names_col"), class = "data.frame", row.names = c("1",
"2", "3", "4"))
<svg height="250" width="500">
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="60%" fy="20%">
<stop offset="0%" style="stop-color:rgb(0,0,0);stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(1,1,1);stop-opacity:1" />
</radialGradient>
</defs>
<circle cx="180" cy="100" r="100" fill="url(#grad1)" />
</svg>