将元素方式的函数应用于data.table列

时间:2016-10-19 20:25:59

标签: r data.table

我有一个data.table,我想将一个函数(例如paste,sum)应用到某些列。例如:

library(data.table)
x = as.data.table(iris)
columnsSelected = c("Sepal.Width", "Sepal.Length")
x[, A := Sepal.Width + Sepal.Length] # this yields the desired result, but not in the way I want.
x[, A := sum(columnsSelected)] # this does not execute
x[, A := sum(get(columnsSelected))] # this does not yield the desired result
x[, A := sum(.SD), .SDcols = columnsSelected] # this does not yield the desired result
x[, A := do.call(sum, .SD), .SDcols = columnsSelected] # same as above

我不知所措。建议Get().SD,但它似乎不适用于多列。关于data.table使用的另一个有趣的讨论是here,但.SDcolstry{ dbConnection = DriverManager.getConnection(DR_URL, DB_USER,DB_PASSWORD); stmt = dbConnection.createStatement(); for(int i=1; i<3; i++){ String invoiceNumber = JOptionPane.showInputDialog("Invoice Number:"); String customerName = JOptionPane.showInputDialog("Customer Name:"); Date invoiceDate = new Date(System.currentTimeMillis()); java.sql.Date invDate = new java.sql.Date (invoiceDate.getTime()); stmt.executeUpdate("INSERT INTO INVOICEMAIN VALUES ('" + invoiceNumber + "','" + customerName + "','" + setDate(invDate) + "')"); } stmt.close(); dbConnection.close(); } 似乎只适用于聚合。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:4)

如果你想要一个明智的元素,那么只需要+而不是sum,它们将所有向量元素加在一起。此外,由于+只接受两个参数,因此您不能将do.call用于两列以上,而是需要Reduce()

x[, A := Reduce("+", .SD), .SDcols = columnsSelected]

#      Sepal.Length Sepal.Width Petal.Length Petal.Width   Species   A
#   1:          5.1         3.5          1.4         0.2    setosa 8.6
#   2:          4.9         3.0          1.4         0.2    setosa 7.9
#   3:          4.7         3.2          1.3         0.2    setosa 7.9
#   4:          4.6         3.1          1.5         0.2    setosa 7.7
#   5:          5.0         3.6          1.4         0.2    setosa 8.6
# ---                                                                
# 146:          6.7         3.0          5.2         2.3 virginica 9.7
# 147:          6.3         2.5          5.0         1.9 virginica 8.8
# 148:          6.5         3.0          5.2         2.0 virginica 9.5
# 149:          6.2         3.4          5.4         2.3 virginica 9.6
# 150:          5.9         3.0          5.1         1.8 virginica 8.9

正如@ 42所评论的那样,我们通过将do.call()变量扩展为三列来了解Reduce()+如何将函数用作paste()columnsSelected

columnsSelected = c("Sepal.Width", "Sepal.Length", "Petal.Length")

其中do.call("+", ...)给出了预期的错误,因为“+”是一个二元运算符并且不接受两个以上的参数,而do.call()给它三个参数({中的三列) {1}}; columnsSelected按预期工作,因为Reduce("+", ...)逐列添加,而不是像Reduce()一样将所有列一次性传递给函数。对于do.call,{ {1}}和paste都可以正常工作,因为do.call()可以接受两个或多个向量作为参数。在这种情况下Reduce()在有很多列时更有效但不应该如果你只传入两三列,那么就在这里。

paste()

do.call()x[, A := do.call(paste, .SD), .SDcols = columnsSelected] # Sepal.Length Sepal.Width Petal.Length Petal.Width Species A # 1: 5.1 3.5 1.4 0.2 setosa 3.5 5.1 1.4 # 2: 4.9 3.0 1.4 0.2 setosa 3 4.9 1.4 # 3: 4.7 3.2 1.3 0.2 setosa 3.2 4.7 1.3 # 4: 4.6 3.1 1.5 0.2 setosa 3.1 4.6 1.5 # 5: 5.0 3.6 1.4 0.2 setosa 3.6 5 1.4 # --- # 146: 6.7 3.0 5.2 2.3 virginica 3 6.7 5.2 # 147: 6.3 2.5 5.0 1.9 virginica 2.5 6.3 5 # 148: 6.5 3.0 5.2 2.0 virginica 3 6.5 5.2 # 149: 6.2 3.4 5.4 2.3 virginica 3.4 6.2 5.4 # 150: 5.9 3.0 5.1 1.8 virginica 3 5.9 5.1 的结果相同。

更新: 要将参数传递给x[, A := Reduce(paste, .SD), .SDcols = columnsSelected]do.call()中的函数,do.call()会对list参数中的参数进行展平,并将它们视为单独的参数,以便将参数传递给{中的函数{1}},我们可以将命名参数连接到list参数,即:

Reduce

另一方面,对于do.call(),它允许您重建匿名函数,您可以创建一个指定了do.call()参数的自定义函数:

x[, A := do.call(paste, c(sep = ",", .SD)), .SDcols = columnsSelected]

#      Sepal.Length Sepal.Width Petal.Length Petal.Width   Species           A
#   1:          5.1         3.5          1.4         0.2    setosa 3.5,5.1,1.4
#   2:          4.9         3.0          1.4         0.2    setosa   3,4.9,1.4
#   3:          4.7         3.2          1.3         0.2    setosa 3.2,4.7,1.3
#   4:          4.6         3.1          1.5         0.2    setosa 3.1,4.6,1.5
#   5:          5.0         3.6          1.4         0.2    setosa   3.6,5,1.4
# ---                                                                        
# 146:          6.7         3.0          5.2         2.3 virginica   3,6.7,5.2
# 147:          6.3         2.5          5.0         1.9 virginica   2.5,6.3,5
# 148:          6.5         3.0          5.2         2.0 virginica   3,6.5,5.2
# 149:          6.2         3.4          5.4         2.3 virginica 3.4,6.2,5.4
# 150:          5.9         3.0          5.1         1.8 virginica   3,5.9,5.1

再次给出与Reduce()相同的结果。