diff --git "a/docs/\345\277\253\351\200\237\346\225\264\347\220\206\357\274\232\345\237\272\344\272\216data.table\347\232\204\346\225\260\346\215\256\345\244\204\347\220\206\345\267\245\345\205\267.html" "b/docs/\345\277\253\351\200\237\346\225\264\347\220\206\357\274\232\345\237\272\344\272\216data.table\347\232\204\346\225\260\346\215\256\345\244\204\347\220\206\345\267\245\345\205\267.html" index 31c59e4..38f4aed 100644 --- "a/docs/\345\277\253\351\200\237\346\225\264\347\220\206\357\274\232\345\237\272\344\272\216data.table\347\232\204\346\225\260\346\215\256\345\244\204\347\220\206\345\267\245\345\205\267.html" +++ "b/docs/\345\277\253\351\200\237\346\225\264\347\220\206\357\274\232\345\237\272\344\272\216data.table\347\232\204\346\225\260\346\215\256\345\244\204\347\220\206\345\267\245\345\205\267.html" @@ -1202,8 +1202,18 @@

< colA = paste("dob_child", 1:3, sep = "") #宽数据转化为长数据,只把dob_child1/dob_child2/dob_child3进行了转化 -DT.m = melt(DT, measure.vars = list(colA), value.name = c("dob")) -DT.m +DT.m = melt(DT, measure.vars = list(colA), value.name = c("dob")) +
+
Warning in melt.data.table(DT, measure.vars = list(colA), value.name =
+c("dob")): measure.vars is a list with length=1, which as long documented
+should return integer indices in the 'variable' column, but currently returns
+character column names. To increase consistency in the next release, we plan to
+change 'variable' to integer, so users who were relying on this behavior should
+change measure.vars=list('col_name') (output variable is column name now, but
+will become column index/integer) to measure.vars='col_name' (variable is
+column name before and after the planned change).
+
+
DT.m
    family_id age_mother gender_child1 gender_child2 gender_child3   variable
         <int>      <int>         <int>         <int>         <int>     <fctr>
@@ -1243,8 +1253,8 @@ 

<

measure.vars可以接收一个或一组变量,即我们需要聚合的列,聚合的变量名可以用variable.name来定义(否则会使用默认的“variable”作为变量名称)。聚合后的值的列名称可以用value.name进行设置,否则会默认使用“value”作为列名(本例中使用了“dob”作为列名)。 如果要把这个长数据还原,可以使用dcast函数,代码如下:

-
DT.c = dcast(DT.m, ...~ variable, value.var = c("dob"))
-DT.c
+
DT.c = dcast(DT.m, ...~ variable, value.var = c("dob"))
+DT.c
Key: <family_id, age_mother, gender_child1, gender_child2, gender_child3>
    family_id age_mother gender_child1 gender_child2 gender_child3 dob_child1
@@ -1265,10 +1275,10 @@ 

<

这里我们要还原的列为variable,而值放在dob列中,其他变量则统统用...来表示。我们看到这个函数的第二个参数必须要用方程式来表示。 下面我们同时进行两个转换(dob和gender)。知道单个转化如何进行,多个的话,只要在后面加一个变量即可。

-
colA = paste0("dob_child", 1:3)
-colB = paste0("gender_child", 1:3)
-DT.m2 = melt(DT, measure.vars = list(colA, colB), value.name = c("dob", "gender"))
-DT.m2
+
colA = paste0("dob_child", 1:3)
+colB = paste0("gender_child", 1:3)
+DT.m2 = melt(DT, measure.vars = list(colA, colB), value.name = c("dob", "gender"))
+DT.m2
    family_id age_mother variable        dob gender
         <int>      <int>   <fctr>     <IDat>  <int>
@@ -1291,8 +1301,8 @@ 

<

它的逆运算也非常简便:

-
DT.c2 = dcast(DT.m2, family_id + age_mother ~ variable, value.var = c("dob", "gender"))
-DT.c2
+
DT.c2 = dcast(DT.m2, family_id + age_mother ~ variable, value.var = c("dob", "gender"))
+DT.c2
Key: <family_id, age_mother>
    family_id age_mother      dob_1      dob_2      dob_3 gender_1 gender_2
@@ -1313,8 +1323,8 @@ 

<

有一个小问题就是,总是需要构造变量名称,然后放在colA和colB中,这样不是特别方便。我们可以用pattern函数来识别列名称的模式,从而简化这个工作:

-
DT.m2 = melt(DT, measure.vars = patterns("^dob", "^gender"), value.name = c("dob", "gender"))
-DT.m2
+
DT.m2 = melt(DT, measure.vars = patterns("^dob", "^gender"), value.name = c("dob", "gender"))
+DT.m2
    family_id age_mother variable        dob gender
         <int>      <int>   <fctr>     <IDat>  <int>
@@ -1357,28 +1367,28 @@ 

5.3.2.1.1 检索

检索是针对用户的需求,来提取总数据集一部分进行查阅,一般可以分为行检索与列检索。 在行检索中,一般是根据数据条目所在位置进行检索。比如我们想要查看iris数据表的第3行,可以这样操作:

-
library(pacman)
-p_load(tidyfst)
-
-iris %>%  slice_dt(3)
+
library(pacman)
+p_load(tidyfst)
+
+iris %>%  slice_dt(3)
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
 1:          4.7         3.2          1.3         0.2  setosa
-

如果想要查看多列,可以使用向量作为检索内容。

+

如果想要查看多行,可以使用向量作为检索内容。

-
# 查看第4和第6列
-iris %>% slice_dt(c(4,6))
+
# 查看第4和第6行
+iris %>% slice_dt(c(4,6))
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
 1:          4.6         3.1          1.5         0.2  setosa
 2:          5.4         3.9          1.7         0.4  setosa
-
# 查看第4到第6列
-iris %>% slice_dt(4:6)
+
# 查看第4到第6行
+iris %>% slice_dt(4:6)
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
@@ -1389,8 +1399,8 @@ 

对列进行检索,则具有更多灵活的选择。首先,与行检索类似,可以根据列所在的位置,来对列进行检索。

-
# 查看第1列
-iris %>% select_dt(1)
+
# 查看第1列
+iris %>% select_dt(1)
     Sepal.Length
             <num>
@@ -1400,8 +1410,8 @@ 
-
# 查看第1和第3列
-iris %>% select_dt(1,3)
+
# 查看第1和第3列
+iris %>% select_dt(1,3)
     Sepal.Length Petal.Length
             <num>        <num>
@@ -1411,8 +1421,8 @@ 
-
# 查看第1到3列
-iris %>% select_dt(1:3)
+
# 查看第1到3列
+iris %>% select_dt(1:3)
     Sepal.Length Sepal.Width Petal.Length
             <num>       <num>        <num>
@@ -1425,8 +1435,8 @@ 

其次,还可以通过变量的名称,直接对其中的一个或多个变量进行检索。

-
# 选择Species列
-iris %>% select_dt(Species)
+
# 选择Species列
+iris %>% select_dt(Species)
       Species
         <fctr>
@@ -1436,8 +1446,8 @@ 
-
# 选择Sepal.Length和Sepal.Width列
-iris %>% select_dt(Sepal.Length,Sepal.Width)
+
# 选择Sepal.Length和Sepal.Width列
+iris %>% select_dt(Sepal.Length,Sepal.Width)
     Sepal.Length Sepal.Width
             <num>       <num>
@@ -1447,8 +1457,8 @@ 
-
# 选择从Sepal.Length列到Petal.Length列中的所有列
-iris %>% select_dt(Sepal.Length:Petal.Length)
+
# 选择从Sepal.Length列到Petal.Length列中的所有列
+iris %>% select_dt(Sepal.Length:Petal.Length)
     Sepal.Length Sepal.Width Petal.Length
             <num>       <num>        <num>
@@ -1461,7 +1471,7 @@ 

如果要按照名称选择多列,还可以使用正则表达式的方法。比如我们要选择列名称中包含“Pe”的列,可以这样操作:

-
iris %>% select_dt("Pe")
+
iris %>% select_dt("Pe")
     Petal.Length Petal.Width
             <num>       <num>
@@ -1474,7 +1484,7 @@ 

与此同时,我们还可以根据数据类型来选择列,比如我们如果需要选择所有的因子变量,可以这样操作:

-
iris %>% select_dt(is.factor)
+
iris %>% select_dt(is.factor)
       Species
         <fctr>
@@ -1487,8 +1497,8 @@ 

如果要去除某些列,在前面加负号(“-“)即可:

-
# 去除Sepal.Length列
-iris %>% select_dt(-Sepal.Length)
+
# 去除Sepal.Length列
+iris %>% select_dt(-Sepal.Length)
     Sepal.Width Petal.Length Petal.Width   Species
            <num>        <num>       <num>    <fctr>
@@ -1498,8 +1508,8 @@ 
-
# 去除第1列
-iris %>% select_dt(-1)
+
# 去除第1列
+iris %>% select_dt(-1)
     Sepal.Width Petal.Length Petal.Width   Species
            <num>        <num>       <num>    <fctr>
@@ -1509,8 +1519,8 @@ 
-
# 去除列名称包含“Se”的列
-iris %>% select_dt(-"Se")
+
# 去除列名称包含“Se”的列
+iris %>% select_dt(-"Se")
     Petal.Length Petal.Width   Species
             <num>       <num>    <fctr>
@@ -1520,8 +1530,8 @@ 
-
# 去除数据类型为因子型的列
-iris %>% select_dt(-is.factor)
+
# 去除数据类型为因子型的列
+iris %>% select_dt(-is.factor)
     Sepal.Length Sepal.Width Petal.Length Petal.Width
             <num>       <num>        <num>       <num>
@@ -1537,7 +1547,7 @@ 
5.3.2.1.2 筛选

筛选操作就是要把数据框中符合条件的行筛选出来,在tidyfst包中可以使用filter_dt函数进行实现。比如我们要筛选iris数据框中Sepal.Length列大于7的条目,可以这样操作:

-
iris %>% filter_dt(Sepal.Length > 7)
+
iris %>% filter_dt(Sepal.Length > 7)
    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
            <num>       <num>        <num>       <num>    <fctr>
@@ -1557,7 +1567,7 @@ 

在筛选条件中,可以使用且(&)、或(|)和非(!)三种逻辑运算符,来表达复杂的条件关系。举个例子,比如我们想要筛选Sepal.Length大于7且Sepal.Width大于3的条目,可以这样操作:

-
iris %>% filter_dt(Sepal.Length > 7 & Sepal.Width > 3)
+
iris %>% filter_dt(Sepal.Length > 7 & Sepal.Width > 3)
   Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
           <num>       <num>        <num>       <num>    <fctr>
@@ -1572,7 +1582,7 @@ 
5.3.2.1.3 排序

在数据框的操作中,可以根据一个或多个变量对行进行排序。tidyfst包中,可以利用arrange_dt函数对排序进行实现。比如,如果我们想要根据Sepal.Length进行排序,可以这样操作:

-
iris %>% arrange_dt(Sepal.Length)
+
iris %>% arrange_dt(Sepal.Length)
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
             <num>       <num>        <num>       <num>    <fctr>
@@ -1585,7 +1595,7 @@ 

从结果中我们可以获知,默认的排序是升序排列。如果需要降序排列,那么需要在变量前面加上负号:

-
iris %>% arrange_dt(-Sepal.Length)
+
iris %>% arrange_dt(-Sepal.Length)
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
             <num>       <num>        <num>       <num>    <fctr>
@@ -1598,8 +1608,8 @@ 

同时,可以加入多个变量,从而在第一个变量相同的情况下,根据第二个变量进行排列:

-
iris %>% arrange_dt(Sepal.Length,Sepal.Width) %>% 
-  head() # 只观察结果的前6行
+
iris %>% arrange_dt(Sepal.Length,Sepal.Width) %>% 
+  head() # 只观察结果的前6行
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
@@ -1617,8 +1627,8 @@ 
5.3.2.1.4 更新

本节提到的更新,具体是指对某一列进行数据的更新,或者通过计算获得一个新的数据列。在tidyfst包中,可以使用mutate_dt函数来对列进行更新。举例来说,比如我们想要让iris数据框中的Sepal.Length列全部加1,可以这样操作:

-
iris %>% 
-  mutate_dt(Sepal.Length = Sepal.Length + 1)
+
iris %>% 
+  mutate_dt(Sepal.Length = Sepal.Length + 1)
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
             <num>       <num>        <num>       <num>    <fctr>
@@ -1631,7 +1641,7 @@ 

我们也可以新增一列,比如我们想要新增一个名称为one的列,这一列的数据为常数1。

-
iris %>% mutate_dt(one = 1)
+
iris %>% mutate_dt(one = 1)
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species   one
             <num>       <num>        <num>       <num>    <fctr> <num>
@@ -1644,9 +1654,9 @@ 

如果我们在更新之后,只想保留更新的那些列,可以使用transmute_dt函数。

-
iris %>% 
-  transmute_dt(one = 1,
-               Sepal.Length = Sepal.Length + 1)
+
iris %>% 
+  transmute_dt(one = 1,
+               Sepal.Length = Sepal.Length + 1)
       one Sepal.Length
      <num>        <num>
@@ -1659,7 +1669,7 @@ 

上面的例子中,我们就仅保留了更新后的两列。 如果需要分组更新,可以使用by参数定义分组信息。比如,我们想要把iris数据框中,根据物种进行分组,然后把Sepal.Length的平均值求出来,附在名为“sp_avg_sl”列中。操作方法如下:

-
iris %>% mutate_dt(sp_avg_sl = mean(Sepal.Length),by = Species)
+
iris %>% mutate_dt(sp_avg_sl = mean(Sepal.Length),by = Species)
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species sp_avg_sl
             <num>       <num>        <num>       <num>    <fctr>     <num>
@@ -1675,7 +1685,7 @@ 
5.3.2.1.5 汇总

汇总,即对一系列数据进行概括的数据操作。求和、求均值、最大值、最小值,均可以视为汇总操作。比如,我们想求iris数据框中Sepal.Length的均值,可以使用tidyfst包的summarise_dt函数。

-
iris %>% summarise_dt(avg = mean(Sepal.Length))
+
iris %>% summarise_dt(avg = mean(Sepal.Length))
        avg
       <num>
@@ -1684,7 +1694,7 @@ 

在上面的操作中,我们把最终输出的列名称设定为“avg”。在实际应用中,我们往往需要进行分组汇总操作,这可以通过设定by参数进行实现。比如我们想知道每个物种Sepal.Length的均值,可以这样操作:

-
iris %>% summarise_dt(avg = mean(Sepal.Length),by = Species)
+
iris %>% summarise_dt(avg = mean(Sepal.Length),by = Species)
      Species   avg
        <fctr> <num>
@@ -1702,11 +1712,11 @@ 

5.3.2.2.1 更新型连接

更新型连接(Mutating joins)是根据两个表格中的共有列进行匹配,然后完成合并的过程,可以分为内连接、外连接、左连接和右连接四种。下面,我们将会构造一个数据集来对四种连接进行说明。

-
library(pacman)
-p_load(tidyfst)
-
-df1 = data.frame(CustomerId = c(1:6), Product = c(rep("洗衣机", 3), rep("微波炉", 3)))
-df1
+
library(pacman)
+p_load(tidyfst)
+
+df1 = data.frame(CustomerId = c(1:6), Product = c(rep("洗衣机", 3), rep("微波炉", 3)))
+df1
  CustomerId Product
 1          1  洗衣机
@@ -1716,8 +1726,8 @@ 
-
df2 = data.frame(CustomerId = c(2, 4, 6), Province = c(rep("广东", 2), rep("北京", 1)))
-df2
+
df2 = data.frame(CustomerId = c(2, 4, 6), Province = c(rep("广东", 2), rep("北京", 1)))
+df2
  CustomerId Province
 1          2     广东
@@ -1727,7 +1737,7 @@ 

在上面的代码中,我们构造了两个数据框(df1和df2)。其中,df1中有消费者的ID号和他们买了什么产品;df2中则包含了消费者ID号和他们所在的地点(省份)。 内连接又称为自然连接,是根据两个表格某一列或多列共有的部分,进行连接的过程。下面,我们来对之前构造的两个表格进行内连接,这可以使用inner_join_dt函数完成。

-
df1 %>% inner_join_dt(df2)
+
df1 %>% inner_join_dt(df2)
Joining by: CustomerId
@@ -1742,7 +1752,7 @@

通过上面的结果,我们可以看到,如果没有设定连接的列,那么inner_join_dt会自动识别两个数据框中的同名列进行匹配。在内连接中,会找到df1和df2同名列CustomerId中完全匹配的条目,进行连接。如果希望直接设定合并的列,可以使用by参数来特殊指定。

-
df1 %>% inner_join_dt(df2,by = "CustomerId")
+
df1 %>% inner_join_dt(df2,by = "CustomerId")
Key: <CustomerId>
    CustomerId Product Province
@@ -1754,7 +1764,7 @@ 

在进行内连接的时候,我们可以看到,如果不匹配的条目,会全部消失。如果想要保留这些条目,可以使用全连接,它会保留两个表格中所有的条目。而没有数值的地方,会自动填充缺失值。

-
df1 %>% full_join_dt(df2)
+
df1 %>% full_join_dt(df2)
Joining by: CustomerId
@@ -1772,7 +1782,7 @@

在上面的结果中,我们可以看到,在df2中没有消费者1、3、5的地区数据,因此填充了缺失值NA。 左连接和右连接是互为逆运算的两个操作,左连接会保留左边数据框的所有信息,但是对于右边的数据框,则只有匹配的数据得以保留,不匹配的部分会填入缺失值。下面我们来进行演示:

-
df1 %>% left_join_dt(df2)
+
df1 %>% left_join_dt(df2)
Joining by: CustomerId
@@ -1787,7 +1797,7 @@
-
df1 %>% right_join_dt(df2)
+
df1 %>% right_join_dt(df2)
Joining by: CustomerId
@@ -1802,23 +1812,23 @@

有的时候,我们需要根据两个或以上的列进行连接,那么将需要通过设置by参数来完成。下面我们举个例子:

-
workers = fread("
-    name company
-    Nick Acme
-    John Ajax
-    Daniela Ajax
-")
-
-positions = fread("
-    name position
-    John designer
-    Daniela engineer
-    Cathie manager
-")
-
-positions2 = setNames(positions, c("worker", "position")) 
-
-workers
+
workers = fread("
+    name company
+    Nick Acme
+    John Ajax
+    Daniela Ajax
+")
+
+positions = fread("
+    name position
+    John designer
+    Daniela engineer
+    Cathie manager
+")
+
+positions2 = setNames(positions, c("worker", "position")) 
+
+workers
      name company
     <char>  <char>
@@ -1826,7 +1836,7 @@ 
-
positions2
+
positions2
    worker position
     <char>   <char>
@@ -1837,7 +1847,7 @@ 

在上面的代码中,我们获得了workers和position2两个数据框。其中,workers数据框中的name为工人名称,而position2数据框中的worker列为数据名称,因此两者合并的时候需要根据名称不同的列进行匹配:

-
workers %>% inner_join_dt(positions2, by = c("name" = "worker"))
+
workers %>% inner_join_dt(positions2, by = c("name" = "worker"))
Key: <name>
       name company position
@@ -1852,7 +1862,7 @@ 
5.3.2.2.2 过滤型连接

过滤型连接(Filtering joins)是根据两个表格中是否有匹配内容来决定一个表格中的观测是否得以保留的操作,在tidyfst包中可以使用anti_join_dtsemi_join_dt实现。其中,anti_join_dt会保留第一个表格有而第二个表格中没有匹配的内容,而semi_join_dt则会保留第一个表格有且第二个表格也有的内容。但是,第二个表格中非匹配列的其他数据不会并入生成表格中。

-
workers %>% anti_join_dt(positions)
+
workers %>% anti_join_dt(positions)
Joining by: name
@@ -1861,7 +1871,7 @@
-
workers %>% semi_join_dt(positions)
+
workers %>% semi_join_dt(positions)
Joining by: name
@@ -1877,36 +1887,36 @@
5.3.2.2.3 集合运算操作

在R中,每个向量都可以视为一个集合,基本包提供了intersect/union/setdiff来求集合的交集、并集和补集,并可以使用setequal函数来查看两个向量是否全等。我们可以做一个简单的演示:

-
x = 1:4
-y = 3:6
-
-union(x, y) #并集
+
x = 1:4
+y = 3:6
+
+union(x, y) #并集
[1] 1 2 3 4 5 6
-
intersect(x, y) #交集
+
intersect(x, y) #交集
[1] 3 4
-
setdiff(x, y) #补集,x有而y没有部分
+
setdiff(x, y) #补集,x有而y没有部分
[1] 1 2
-
setdiff(y, x) #补集,y有而x没有部分
+
setdiff(y, x) #补集,y有而x没有部分
[1] 5 6
-
setequal(x, y) # x与y是否相等
+
setequal(x, y) # x与y是否相等
[1] FALSE

而在tidyfst中,利用了data.table的集合运算函数,可以直接对数据框进行对应的集合运算操作。需要注意的是,所求数据框需要有相同的列名称。下面我们利用iris的前3列来做一个简单的演示:

-
x = iris[1:2,]
-y = iris[2:3,] 
-
-union_dt(x, y) #并集
+
x = iris[1:2,]
+y = iris[2:3,] 
+
+union_dt(x, y) #并集
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
@@ -1914,32 +1924,32 @@ 
-
intersect_dt(x, y) #交集
+
intersect_dt(x, y) #交集
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
 1:          4.9           3          1.4         0.2  setosa
-
setdiff_dt(x, y) #补集,x有而y没有部分
+
setdiff_dt(x, y) #补集,x有而y没有部分
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
 1:          5.1         3.5          1.4         0.2  setosa
-
setdiff_dt(y, x) #补集,y有而x没有部分
+
setdiff_dt(y, x) #补集,y有而x没有部分
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
 1:          4.7         3.2          1.3         0.2  setosa
-
setequal_dt(x, y) # x与y是否相等
+
setequal_dt(x, y) # x与y是否相等
[1] FALSE

这些函数都有all参数,可以调节其对重复值的处理。比如,如果我们取并集的时候,不需要去重,那么可以设置“all = TRUE”。

-
union_dt(x,y,all = TRUE)
+
union_dt(x,y,all = TRUE)
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
           <num>       <num>        <num>       <num>  <fctr>
@@ -1966,15 +1976,15 @@ 

delete_na_rows:行删除操作,如果数据框中任意行的缺失值比例或数量超过一个阈值,将整个列删除掉。

下面,我们将举个例子对上述操作进行演示。首先我们要构建一个缺失值数据框。

-
library(pacman)
-p_load(tidyfst)
-
-df <- data.frame(col1 = c(1:3, NA),
-                 col2 = c("this", NA,NA, "text"), 
-                 col3 = c(TRUE, FALSE, TRUE, TRUE), 
-                 col4 = c(NA, NA, 3.2, NA))
-
-df
+
library(pacman)
+p_load(tidyfst)
+
+df <- data.frame(col1 = c(1:3, NA),
+                 col2 = c("this", NA,NA, "text"), 
+                 col3 = c(TRUE, FALSE, TRUE, TRUE), 
+                 col4 = c(NA, NA, 3.2, NA))
+
+df
  col1 col2  col3 col4
 1    1 this  TRUE   NA
@@ -1985,7 +1995,7 @@ 

所构造的数据框中,第一、二、三、四列分别有1、2、0和3个缺失值。我们如果想要删除col2中包含缺失值的条目,可以使用drop_na_dt函数。

-
df %>% drop_na_dt(col2)
+
df %>% drop_na_dt(col2)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -1995,8 +2005,8 @@ 

如果想要删除缺失值大于等于2个或缺失比例大于等于50%的列,则可以这样操作:

-
# 删除缺失值大于等于2个的列
-df %>% delete_na_cols(n = 2)
+
# 删除缺失值大于等于2个的列
+df %>% delete_na_cols(n = 2)
    col1   col3
    <int> <lgcl>
@@ -2005,8 +2015,8 @@ 
-
# 删除缺失比例大于等于50%的列
-df %>% delete_na_cols(prop = 0.5) 
+
# 删除缺失比例大于等于50%的列
+df %>% delete_na_cols(prop = 0.5) 
    col1   col3
    <int> <lgcl>
@@ -2018,16 +2028,16 @@ 

如果想要删除缺失值大于等于2个或缺失比例大于等于50%的行,则可以这样操作:

-
# 删除缺失值大于等于2个的行
-df %>% delete_na_rows(n = 2)
+
# 删除缺失值大于等于2个的行
+df %>% delete_na_rows(n = 2)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
 1:     1   this   TRUE    NA
 2:     3   <NA>   TRUE   3.2
-
# 删除缺失比例大于等于50%的行
-df %>% delete_na_rows(prop = 0.5)
+
# 删除缺失比例大于等于50%的行
+df %>% delete_na_rows(prop = 0.5)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2041,8 +2051,8 @@ 
5.3.3.1.2 缺失值替换

缺失值替换就是把缺失的部分用指定数据进行替代的过程,在tidyfst中可以使用replace_na_dt进行实现。比如,我们要将上面所构造数据框的col1列缺失值替换为-99,可以这样操作:

-
df %>% 
-  replace_na_dt(col1,to = -99)
+
df %>% 
+  replace_na_dt(col1,to = -99)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2054,8 +2064,8 @@ 

也可以同时对col1和col4同时进行这项操作:

-
df %>% 
-  replace_na_dt(col1,col4,to = -99)
+
df %>% 
+  replace_na_dt(col1,col4,to = -99)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2067,9 +2077,9 @@ 

如果不设定替换列,默认替换所有的列。但需要注意的是,每一个列的类型都不一样,因此在替换的时候需要保证替换列数据类型的一致性。

-
df %>% 
-  mutate_vars(.func = as.character) %>% #将有所列转化为字符型
-  replace_na_dt(to = "missing") #将缺失值替换为“missing”
+
df %>% 
+  mutate_vars(.func = as.character) %>% #将有所列转化为字符型
+  replace_na_dt(to = "missing") #将缺失值替换为“missing”
      col1    col2   col3    col4
     <char>  <char> <char>  <char>
@@ -2088,8 +2098,8 @@ 

impute_dt:根据列汇总数据(平均值、中位数、众数或其他)来对缺失值进行插补

我们先对fill_na_dt函数进行讲解,它的原理非常简单,我们直接进行演示。

-
# 对col2向下进行插补
-df %>% fill_na_dt(col2)
+
# 对col2向下进行插补
+df %>% fill_na_dt(col2)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2098,8 +2108,8 @@ 
-
# 对col2向上进行插补
-df %>% fill_na_dt(col2,direction = "up")
+
# 对col2向上进行插补
+df %>% fill_na_dt(col2,direction = "up")
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2108,8 +2118,8 @@ 
-
# 对数值型列进行向下插补
-df %>% fill_na_dt(is.numeric)
+
# 对数值型列进行向下插补
+df %>% fill_na_dt(is.numeric)
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2118,8 +2128,8 @@ 
-
# 对所有列进行向上插补
-df %>% fill_na_dt(direction = "up")
+
# 对所有列进行向上插补
+df %>% fill_na_dt(direction = "up")
    col1   col2   col3  col4
    <int> <char> <lgcl> <num>
@@ -2131,7 +2141,7 @@ 

有的时候,我们会尝试用均值来对数值型的变量进行插值,那么我们可以使用impute_dt函数进行操作:

-
df %>% impute_dt(is.numeric,.func = "mean")
+
df %>% impute_dt(is.numeric,.func = "mean")
    col1   col2   col3  col4
    <num> <char> <lgcl> <num>
@@ -2149,13 +2159,13 @@ 
5.3.3.2 长宽数据转换

表格的长宽转换是一个经典的数据操作,它可以自由地改变二维表的结构。比如我们之前熟悉的iris数据框,其实就可以转化为任意的其他结构。举个例子,我们给每一朵花都进行编号,然后直接转为长表格式。

-
library(pacman)
-p_load(tidyfst)
-
-iris %>% 
-  mutate_vars(.func = as.character) %>%  #所有数据转化为字符型
-  mutate_dt(id = 1:.N) %>%  # 给所有花进行编号
-  longer_dt(id) # 以编号id作为分组变量,转化为长表
+
library(pacman)
+p_load(tidyfst)
+
+iris %>% 
+  mutate_vars(.func = as.character) %>%  #所有数据转化为字符型
+  mutate_dt(id = 1:.N) %>%  # 给所有花进行编号
+  longer_dt(id) # 以编号id作为分组变量,转化为长表
        id         name     value
      <int>       <fctr>    <char>
@@ -2171,110 +2181,110 @@ 

5.3.3.2.1 宽表转长表

tidyfst包中,可以使用longer_dt函数来把宽表转化为长表,需要定义的核心参数是数据框和分组列。分组列就是不参与长宽变换的列,而其他列名称将会统统聚合起来成为一列。下面我们进行一个简单的演示。首先,我们先进行数据准备:

-
stocks = data.frame(
-  time = as.Date('2009-01-01') + 0:9,
-  X = rnorm(10, 0, 1),
-  Y = rnorm(10, 0, 2),
-  Z = rnorm(10, 0, 4)
-)
-
-stocks
-
-
         time           X          Y          Z
-1  2009-01-01 -0.41951421 -4.0696697  1.1862528
-2  2009-01-02 -1.95653982  1.2851513 -4.3121715
-3  2009-01-03 -0.18057417  0.2530406  1.4529063
-4  2009-01-04  1.53254389  2.5200584  1.2337196
-5  2009-01-05 -0.40798547 -3.1497638 -2.6830911
-6  2009-01-06  2.09614174  4.4814026  2.1697771
-7  2009-01-07 -0.39973265 -0.4680301  1.6492286
-8  2009-01-08  0.33918122 -2.1085464  1.9916131
-9  2009-01-09  0.25558423  2.7826645  0.3446163
-10 2009-01-10 -0.09429387 -0.9727120 -1.4884806
+
stocks = data.frame(
+  time = as.Date('2009-01-01') + 0:9,
+  X = rnorm(10, 0, 1),
+  Y = rnorm(10, 0, 2),
+  Z = rnorm(10, 0, 4)
+)
+
+stocks
+
+
         time            X           Y          Z
+1  2009-01-01  0.281683357  0.76471698 -2.5342818
+2  2009-01-02  0.623717987 -2.68345066 -3.4767958
+3  2009-01-03 -1.095659662  1.55443409 -2.2950831
+4  2009-01-04  0.340494860 -0.62615790  1.6633414
+5  2009-01-05  1.637452081  1.74396217  5.2667718
+6  2009-01-06  0.005707745 -4.29363758  5.9902291
+7  2009-01-07 -0.495548864 -1.22534932  6.4509272
+8  2009-01-08  1.001418629 -0.02843278 -4.8999951
+9  2009-01-09  1.919028184  3.46398763 -4.0807348
+10 2009-01-10  0.081246615  2.18895188  0.2073267

观察数据,我们知道这是一个10行4列的数据框,一列为时间time,其余三列为数值列。现在,我们要把它转化为长表。

-
stocks %>% 
-  longer_dt(time) -> longer_table
-
-longer_table
-
-
          time   name       value
-        <Date> <fctr>       <num>
- 1: 2009-01-01      X -0.41951421
- 2: 2009-01-02      X -1.95653982
- 3: 2009-01-03      X -0.18057417
- 4: 2009-01-04      X  1.53254389
- 5: 2009-01-05      X -0.40798547
- 6: 2009-01-06      X  2.09614174
- 7: 2009-01-07      X -0.39973265
- 8: 2009-01-08      X  0.33918122
- 9: 2009-01-09      X  0.25558423
-10: 2009-01-10      X -0.09429387
-11: 2009-01-01      Y -4.06966965
-12: 2009-01-02      Y  1.28515135
-13: 2009-01-03      Y  0.25304059
-14: 2009-01-04      Y  2.52005836
-15: 2009-01-05      Y -3.14976381
-16: 2009-01-06      Y  4.48140262
-17: 2009-01-07      Y -0.46803013
-18: 2009-01-08      Y -2.10854639
-19: 2009-01-09      Y  2.78266455
-20: 2009-01-10      Y -0.97271195
-21: 2009-01-01      Z  1.18625279
-22: 2009-01-02      Z -4.31217152
-23: 2009-01-03      Z  1.45290630
-24: 2009-01-04      Z  1.23371964
-25: 2009-01-05      Z -2.68309108
-26: 2009-01-06      Z  2.16977710
-27: 2009-01-07      Z  1.64922855
-28: 2009-01-08      Z  1.99161315
-29: 2009-01-09      Z  0.34461627
-30: 2009-01-10      Z -1.48848060
-          time   name       value
+
stocks %>% 
+  longer_dt(time) -> longer_table
+
+longer_table
+
+
          time   name        value
+        <Date> <fctr>        <num>
+ 1: 2009-01-01      X  0.281683357
+ 2: 2009-01-02      X  0.623717987
+ 3: 2009-01-03      X -1.095659662
+ 4: 2009-01-04      X  0.340494860
+ 5: 2009-01-05      X  1.637452081
+ 6: 2009-01-06      X  0.005707745
+ 7: 2009-01-07      X -0.495548864
+ 8: 2009-01-08      X  1.001418629
+ 9: 2009-01-09      X  1.919028184
+10: 2009-01-10      X  0.081246615
+11: 2009-01-01      Y  0.764716980
+12: 2009-01-02      Y -2.683450664
+13: 2009-01-03      Y  1.554434086
+14: 2009-01-04      Y -0.626157901
+15: 2009-01-05      Y  1.743962172
+16: 2009-01-06      Y -4.293637579
+17: 2009-01-07      Y -1.225349317
+18: 2009-01-08      Y -0.028432778
+19: 2009-01-09      Y  3.463987634
+20: 2009-01-10      Y  2.188951879
+21: 2009-01-01      Z -2.534281801
+22: 2009-01-02      Z -3.476795793
+23: 2009-01-03      Z -2.295083131
+24: 2009-01-04      Z  1.663341410
+25: 2009-01-05      Z  5.266771836
+26: 2009-01-06      Z  5.990229085
+27: 2009-01-07      Z  6.450927170
+28: 2009-01-08      Z -4.899995125
+29: 2009-01-09      Z -4.080734833
+30: 2009-01-10      Z  0.207326711
+          time   name        value

可以发现,列名称X/Y/Z都在name列中,其值则在value列中。这些列名称可以通过更改namevalue参数重新被定义。

-
stocks %>% 
-  longer_dt(time,
-            name = "var",
-            value = "val") 
-
-
          time    var         val
-        <Date> <fctr>       <num>
- 1: 2009-01-01      X -0.41951421
- 2: 2009-01-02      X -1.95653982
- 3: 2009-01-03      X -0.18057417
- 4: 2009-01-04      X  1.53254389
- 5: 2009-01-05      X -0.40798547
- 6: 2009-01-06      X  2.09614174
- 7: 2009-01-07      X -0.39973265
- 8: 2009-01-08      X  0.33918122
- 9: 2009-01-09      X  0.25558423
-10: 2009-01-10      X -0.09429387
-11: 2009-01-01      Y -4.06966965
-12: 2009-01-02      Y  1.28515135
-13: 2009-01-03      Y  0.25304059
-14: 2009-01-04      Y  2.52005836
-15: 2009-01-05      Y -3.14976381
-16: 2009-01-06      Y  4.48140262
-17: 2009-01-07      Y -0.46803013
-18: 2009-01-08      Y -2.10854639
-19: 2009-01-09      Y  2.78266455
-20: 2009-01-10      Y -0.97271195
-21: 2009-01-01      Z  1.18625279
-22: 2009-01-02      Z -4.31217152
-23: 2009-01-03      Z  1.45290630
-24: 2009-01-04      Z  1.23371964
-25: 2009-01-05      Z -2.68309108
-26: 2009-01-06      Z  2.16977710
-27: 2009-01-07      Z  1.64922855
-28: 2009-01-08      Z  1.99161315
-29: 2009-01-09      Z  0.34461627
-30: 2009-01-10      Z -1.48848060
-          time    var         val
+
stocks %>% 
+  longer_dt(time,
+            name = "var",
+            value = "val") 
+
+
          time    var          val
+        <Date> <fctr>        <num>
+ 1: 2009-01-01      X  0.281683357
+ 2: 2009-01-02      X  0.623717987
+ 3: 2009-01-03      X -1.095659662
+ 4: 2009-01-04      X  0.340494860
+ 5: 2009-01-05      X  1.637452081
+ 6: 2009-01-06      X  0.005707745
+ 7: 2009-01-07      X -0.495548864
+ 8: 2009-01-08      X  1.001418629
+ 9: 2009-01-09      X  1.919028184
+10: 2009-01-10      X  0.081246615
+11: 2009-01-01      Y  0.764716980
+12: 2009-01-02      Y -2.683450664
+13: 2009-01-03      Y  1.554434086
+14: 2009-01-04      Y -0.626157901
+15: 2009-01-05      Y  1.743962172
+16: 2009-01-06      Y -4.293637579
+17: 2009-01-07      Y -1.225349317
+18: 2009-01-08      Y -0.028432778
+19: 2009-01-09      Y  3.463987634
+20: 2009-01-10      Y  2.188951879
+21: 2009-01-01      Z -2.534281801
+22: 2009-01-02      Z -3.476795793
+23: 2009-01-03      Z -2.295083131
+24: 2009-01-04      Z  1.663341410
+25: 2009-01-05      Z  5.266771836
+26: 2009-01-06      Z  5.990229085
+27: 2009-01-07      Z  6.450927170
+28: 2009-01-08      Z -4.899995125
+29: 2009-01-09      Z -4.080734833
+30: 2009-01-10      Z  0.207326711
+          time    var          val
@@ -2282,58 +2292,58 @@
5.3.3.2.2 长表转宽表

长表转为宽表是宽表转长表的逆运算,因此需要定义的核心参数也有相仿之处,需要知道数据框、分组列的信息,同时需要知道名称列(name)和数值列(value)分别来自哪里。以上面生成的longer_table为例,我们尝试把它进行还原。

-
longer_table
-
-
          time   name       value
-        <Date> <fctr>       <num>
- 1: 2009-01-01      X -0.41951421
- 2: 2009-01-02      X -1.95653982
- 3: 2009-01-03      X -0.18057417
- 4: 2009-01-04      X  1.53254389
- 5: 2009-01-05      X -0.40798547
- 6: 2009-01-06      X  2.09614174
- 7: 2009-01-07      X -0.39973265
- 8: 2009-01-08      X  0.33918122
- 9: 2009-01-09      X  0.25558423
-10: 2009-01-10      X -0.09429387
-11: 2009-01-01      Y -4.06966965
-12: 2009-01-02      Y  1.28515135
-13: 2009-01-03      Y  0.25304059
-14: 2009-01-04      Y  2.52005836
-15: 2009-01-05      Y -3.14976381
-16: 2009-01-06      Y  4.48140262
-17: 2009-01-07      Y -0.46803013
-18: 2009-01-08      Y -2.10854639
-19: 2009-01-09      Y  2.78266455
-20: 2009-01-10      Y -0.97271195
-21: 2009-01-01      Z  1.18625279
-22: 2009-01-02      Z -4.31217152
-23: 2009-01-03      Z  1.45290630
-24: 2009-01-04      Z  1.23371964
-25: 2009-01-05      Z -2.68309108
-26: 2009-01-06      Z  2.16977710
-27: 2009-01-07      Z  1.64922855
-28: 2009-01-08      Z  1.99161315
-29: 2009-01-09      Z  0.34461627
-30: 2009-01-10      Z -1.48848060
-          time   name       value
-
-
longer_table %>% 
-  wider_dt(time,name = "name",value = "value")
+
longer_table
+
+
          time   name        value
+        <Date> <fctr>        <num>
+ 1: 2009-01-01      X  0.281683357
+ 2: 2009-01-02      X  0.623717987
+ 3: 2009-01-03      X -1.095659662
+ 4: 2009-01-04      X  0.340494860
+ 5: 2009-01-05      X  1.637452081
+ 6: 2009-01-06      X  0.005707745
+ 7: 2009-01-07      X -0.495548864
+ 8: 2009-01-08      X  1.001418629
+ 9: 2009-01-09      X  1.919028184
+10: 2009-01-10      X  0.081246615
+11: 2009-01-01      Y  0.764716980
+12: 2009-01-02      Y -2.683450664
+13: 2009-01-03      Y  1.554434086
+14: 2009-01-04      Y -0.626157901
+15: 2009-01-05      Y  1.743962172
+16: 2009-01-06      Y -4.293637579
+17: 2009-01-07      Y -1.225349317
+18: 2009-01-08      Y -0.028432778
+19: 2009-01-09      Y  3.463987634
+20: 2009-01-10      Y  2.188951879
+21: 2009-01-01      Z -2.534281801
+22: 2009-01-02      Z -3.476795793
+23: 2009-01-03      Z -2.295083131
+24: 2009-01-04      Z  1.663341410
+25: 2009-01-05      Z  5.266771836
+26: 2009-01-06      Z  5.990229085
+27: 2009-01-07      Z  6.450927170
+28: 2009-01-08      Z -4.899995125
+29: 2009-01-09      Z -4.080734833
+30: 2009-01-10      Z  0.207326711
+          time   name        value
+
+
longer_table %>% 
+  wider_dt(time,name = "name",value = "value")
Key: <time>
-          time           X          Y          Z
-        <Date>       <num>      <num>      <num>
- 1: 2009-01-01 -0.41951421 -4.0696697  1.1862528
- 2: 2009-01-02 -1.95653982  1.2851513 -4.3121715
- 3: 2009-01-03 -0.18057417  0.2530406  1.4529063
- 4: 2009-01-04  1.53254389  2.5200584  1.2337196
- 5: 2009-01-05 -0.40798547 -3.1497638 -2.6830911
- 6: 2009-01-06  2.09614174  4.4814026  2.1697771
- 7: 2009-01-07 -0.39973265 -0.4680301  1.6492286
- 8: 2009-01-08  0.33918122 -2.1085464  1.9916131
- 9: 2009-01-09  0.25558423  2.7826645  0.3446163
-10: 2009-01-10 -0.09429387 -0.9727120 -1.4884806
+ time X Y Z + <Date> <num> <num> <num> + 1: 2009-01-01 0.281683357 0.76471698 -2.5342818 + 2: 2009-01-02 0.623717987 -2.68345066 -3.4767958 + 3: 2009-01-03 -1.095659662 1.55443409 -2.2950831 + 4: 2009-01-04 0.340494860 -0.62615790 1.6633414 + 5: 2009-01-05 1.637452081 1.74396217 5.2667718 + 6: 2009-01-06 0.005707745 -4.29363758 5.9902291 + 7: 2009-01-07 -0.495548864 -1.22534932 6.4509272 + 8: 2009-01-08 1.001418629 -0.02843278 -4.8999951 + 9: 2009-01-09 1.919028184 3.46398763 -4.0807348 +10: 2009-01-10 0.081246615 2.18895188 0.2073267

在上面的操作中,我们把time定义为分组列,然后以字符形式来定义哪一列是名称列,哪一列是数值列。在宽表转长表的时候,namevalue如果不自定义,就会自动给名称列命名为“name”,给数值列命名为“value”;但是在长表转为宽表的时候,则必须手动进行定义,否则计算机无法自动识别。