vue data拓展运算符
当您利用R data.table代码的特殊符号和功能时,它会变得更加高效且优雅。 考虑到这一点,我们将研究一些子集,计数和创建新列的特殊方法。
对于此演示,我将使用2019年Stack Overflow开发人员调查中的数据,大约有90,000个响应。 如果要继续学习,可以从Stack Overflow 下载数据 。
如果您的系统上未安装data.table软件包,请从CRAN安装它,然后像往常一样使用library(data.table)
加载它。 首先,您可能只想读入数据集的前几行,以便更轻松地检查数据结构。 您可以使用data.table的fread()
函数和nrows
参数来实现。 我将阅读10行:
data_sample <- fread("data/survey_results_public.csv", nrows = 10)
如您所见,有85列要检查。 (如果您想知道所有列的含义,则下载的文件中包含数据模式和原始调查的PDF。)
要读取所有数据,我将使用:
mydt <- fread("data/survey_results_public.csv")
接下来,我将创建一个只有几列的新的data.table,以使其更易于使用和查看结果。 提醒您data.table使用以下基本语法:
mydt[i, j, by]
data.table程序包的介绍说,将其理解为“使用i获取dt,子集或对行进行重新排序,计算j,按...分组”。 请记住,i和j与基R的括号排序类似:第一行,第二列。 因此,我适合您要对行执行的操作(根据行号或条件选择行); j是您要对列执行的操作(选择列或从计算中创建新列)。 但是,还请注意,与基本R数据框相比,您可以在data.table括号内做更多的事情。 而且“ by”部分是data.table的新功能。
由于我正在选择列,因此该代码位于“ j”位置,这意味着方括号需要首先使用逗号将“ i”位置保留为空:
mydt[, j]
选择data.table列
我喜欢data.table的一件事是,很容易选择带引号或不带引号的列。 不带引号通常更方便(通常是整齐的方式)。 但是如果在自己的函数中使用data.table,或者要传递在代码中其他位置创建的向量,则使用引号很有用。
您可以选择典型的基数R方式的data.table列,并使用带引号的列名称的常规向量。 例如:
dt1 <- mydt[, c("LanguageWorkedWith", "LanguageDesireNextYear",
"OpenSourcer", "CurrencySymbol", "ConvertedComp”,
“Hobbyist”)]
如果要不加引号使用它们,请创建一个列表而不是一个矢量,然后可以传入未加引号的名称。
dt1 <- mydt[, list(LanguageWorkedWith, LanguageDesireNextYear,
OpenSourcer, CurrencySymbol, ConvertedComp,
Hobbyist)]
现在我们来第一个特殊符号。 除了输入list()
,您还可以使用一个点:
dt1 <- mydt[, .(LanguageWorkedWith, LanguageDesireNextYear,
OpenSourcer, CurrencySymbol, ConvertedComp,
Hobbyist)]
.()
是data.table括号内list()
的快捷方式。
如果要使用已经存在的列名向量怎么办? 将矢量对象名称放在data.table括号内将不起作用。 如果我创建带有引号的列名的向量,如下所示:
mycols <- c("LanguageWorkedWith", "LanguageDesireNextYear",
"OpenSourcer", "CurrencySymbol", "ConvertedComp", "Hobbyist")
然后此代码将无法工作:
dt1 <- mydt[, mycols]
相反,您需要在矢量对象名称的前面放置..
(两个点):
dt1 <- mydt[, ..mycols]
为什么要两个点? 在我阅读解释之前,这对我来说似乎是随机的。 可以将其想像成Unix命令行终端中的两个点,它们将您向上移动一个目录。 在这里,您正在从data.table括号内的环境到全局环境上移一个名称空间 。 (这确实帮助我记住了!)
计数数据表行
转到下一个符号。 要按组计数,可以使用data.table的.N
符号,其中.N
代表“行数”。 它可以是总行数,也可以是每个组的行数(如果您在“ by”部分中进行汇总)。
此表达式返回data.table中的总行数:
mydt[, .N]
以下示例计算按一个变量分组的行数:调查中的人是否也将代码编码为嗜好( Hobbyist
变量)。
mydt[, .N, Hobbyist]
# returns:
Hobbyist N
1: Yes 71257
2: No 17626
如果只有一个变量,则可以在data.table括号内使用普通列名称。 如果要按两个或多个变量分组,请使用.
符号。 例如:
mydt[, .N, .(Hobbyist, OpenSourcer)]
要从最高到最低排序结果,可以在第一组之后添加第二组。 .N
符号会自动生成一个名为N的列(当然,您可以根据需要对其进行重命名),因此按行数排序的方式如下所示:
mydt[, .N, .(Hobbyist, OpenSourcer)][order(Hobbyist, -N)]
在学习data.table代码时,我发现逐步阅读它很有帮助。 因此,我将其读为“对于mydt中的所有行(因为“ I”位置中没有任何内容),对行数进行计数,并按Hobbyist和OpenSourcer进行分组。 然后先由Hobbyist排序,然后行数降序。”
等效于以下dplyr代码:
mydf %>%
count(Hobbyist, OpenSourcer) %>%
order(Hobbyist, -n)
如果您发现tidyverse常规多行方法更具可读性,那么此data.table代码也可以工作:
mydt[, .N,
.(Hobbyist, OpenSourcer)][
order(Hobbyist, -N)
]
将列添加到data.table
接下来,我想添加列以查看每个响应者是否使用R,是否使用Python,是否都使用R或都不使用R。 LanguageWorkedWith
列包含有关所用LanguageWorkedWith
信息,该数据的几行如下所示:
每个答案都是一个字符串。 大多数语言有多种语言,用分号分隔。
通常,搜索Python比R更容易,因为您不能像搜索“ Python”那样仅在字符串中搜索“ R”(Ruby和Rust也包含大写的R)。 这是创建TRUE / FALSE向量的更简单的代码,该向量检查LanguageWorkedWith
中的每个字符串是否包含Python:
ifelse(LanguageWorkedWith %like% "Python", TRUE, FALSE)
如果您知道SQL,就会认识到这种“赞”语法。 我,就像%like%.
这是检查模式匹配的一种很好的简化方法。 函数文档说,它打算在data.table括号内使用,但实际上您可以在任何代码中使用它,而不仅仅是data.tables。 我与data.table的创建者Matt Dowle进行了核对,他说在括号内使用它的建议是因为在那里进行了一些额外的性能优化。
接下来,下面的代码将一个名为PythonUser的列添加到data.table中:
dt1[, PythonUser := ifelse(LanguageWorkedWith %like% "Python", TRUE, FALSE)]
注意:=
运算符。 Python也有类似的运算符,自从我听说它被称为“海象运算符”以来,这就是我所说的。 我认为这是正式的“参考转让”。 这是因为上面的代码通过添加新列更改了现有对象dt1 data.table, 而无需将其保存到新变量中。
要搜索R,我将使用正则表达式"\\bR\\b"
表示:“找到一个以单词边界开头的模式- \\b
,然后是R
,然后以另一个单词边界结束。 (我不能只寻找“ R;”,因为每个字符串中的最后一项没有分号。)
这会将RUser列添加到dt1:
dt1[, RUser := ifelse(LanguageWorkedWith %like% "\\bR\\b", TRUE, FALSE)]
如果要使用:=
一次添加两列,则需要通过反引号将该海象运算符转换为函数,如下所示:
dt1[,`:=` (
PythonUser = ifelse(LanguageWorkedWith %like% "Python", TRUE, FALSE),
RUser = ifelse(LanguageWorkedWith %like% "\\bR\\b", TRUE, FALSE)
)]
更有用的data.table运算符
还有其他一些data.table运算符值得了解。 %between%
运算符具有以下语法:
myvector %between% c(lower_value, upper_value)
因此,如果我要过滤所有补偿金额在50,000到100,000美元之间的所有响应,则此代码有效:
comp_50_100k <- dt1[CurrencySymbol == "USD" &
ConvertedComp %between% c(50000, 100000)]
上面的第二行是介于两者之间的条件。 请注意, %between%
运算符在检查时包括下限值和上限值。
另一个有用的运算符是%chin%
。 它的工作方式类似于基R的%in%
但针对速度进行了优化,并且仅适用于字符向量 。 因此,如果我想过滤OpenSourcer列为“从不”或“每年少于一次”的所有行,则此代码有效:
rareos <- dt1[OpenSourcer %chin% c("Never", "Less than once per year")]
这与基本R非常相似,不同之处在于基本R必须在括号内指定数据框名称,并且在过滤器表达式后还需要逗号:
rareos_df <- df1[df1$OpenSourcer %in% c("Never", "Less than once per year"),]
新的fcase()函数
对于此最终演示,我将首先创建一个新的data.table,其中仅包含以美元报告的人:
usd <- dt1[CurrencySymbol == "USD" & !is.na(ConvertedComp)]
接下来,我将创建一个名为Language
的新列,用于说明某人是仅使用R,仅使用Python还是不使用。 我将使用新的fcase()
函数。 在本文发布时, fcase()
仅在data.table的开发版本中可用。 如果已经安装了data.table,则可以使用以下命令更新到最新的dev版本:
data.table::update.dev.pkg()
fcase()函数类似于SQL的CASE WHEN
语句和dplyr的case_when()
函数。 基本语法为fcase(condition1, "value1", condition2, "value2")
等。 可以使用default = value
添加“其他所有内容”的default = value
。
这是创建新的“语言”列的代码:
usd[, Language := fcase(
RUser & !PythonUser, "R",
PythonUser & !RUser, "Python",
PythonUser & RUser, "Both",
!PythonUser & !RUser, "Neither"
)]
我将每个条件放在单独的行上,因为我发现它更易于阅读,但您不必这样做。
注意:如果您使用的是RStudio,则使用walrus运算符创建新列后,data.table结构不会在RStudio右上角自动更新。 您需要手动单击刷新图标以查看列数的更改。
在本文中我将不介绍其他一些符号。 您可以通过运行help("special-symbols")
在“特殊符号” data.table帮助文件中找到它们的列表。 最有用的.SD之一已经有了自己的《用R做更多事情 》文章和视频,“ 如何在R data.table包中使用.SD ”。
有关R的更多技巧,请转到InfoWorld上的“用R做更多”页面,或查看YouTube播放列表中的“用R做更多” 。
翻译自: https://www.infoworld.com/article/3530348/r-datatable-symbols-and-operators-you-should-know.html
vue data拓展运算符