أنا أحب هذه العناصر data.table ، بالتساوي لسرعة تنفيذها وطريقتها البخل في البرمجة النصية.
أنا أستخدمه حتى على الطاولات الصغيرة أيضًا.
أقوم بانتظام بتقسيم الجداول بهذه الطريقة: DT [،. (id1، id5)]
وليس بهذه الطريقة: DT [، c ("id1"، "id5")]
لقد قمت اليوم بقياس سرعة الاثنين وقد اندهشت من اختلاف السرعة على الطاولات الصغيرة. الطريقة البخل بطيئة.
هل هذا الاختلاف شيء مقصود؟
هل هناك طموح في شق طريق التقارب من حيث سرعة التنفيذ إلى الآخر؟
(يتم احتسابها عندما يتعين عليّ تقسيم عدة جداول صغيرة بطريقة متكررة.)
أوبونتو 18.04.2018
R الإصدار 3.5.3 (2019-03-11)
جدول البيانات 1.12.0
ذاكرة عشوائية 32 جيجا بايت
Intel® Core ™ i7-8565U CPU @ 1.80 جيجاهرتز × 8
library(data.table)
library(microbenchmark)
N <- 2e8
K <- 100
set.seed(1)
DT <- data.table(
id1 = sample(sprintf("id%03d", 1:K), N, TRUE), # large groups (char)
id2 = sample(sprintf("id%03d", 1:K), N, TRUE), # large groups (char)
id3 = sample(sprintf("id%010d", 1:(N/K)), N, TRUE), # small groups (char)
id4 = sample(K, N, TRUE), # large groups (int)
id5 = sample(K, N, TRUE), # large groups (int)
id6 = sample(N/K, N, TRUE), # small groups (int)
v1 = sample(5, N, TRUE), # int in range [1,5]
v2 = sample(5, N, TRUE), # int in range [1,5]
v3 = sample(round(runif(100, max = 100), 4), N, TRUE) # numeric e.g. 23.5749
)
microbenchmark(
DT[, .(id1, id5)],
DT[, c("id1", "id5")]
)
Unit: seconds
expr min lq mean median uq max neval
DT[, .(id1, id5)] 1.588367 1.614645 1.929348 1.626847 1.659698 12.33872 100
DT[, c("id1", "id5")] 1.592154 1.613800 1.937548 1.628082 2.184456 11.74581 100
N <- 2e5
DT2 <- data.table(
id1 = sample(sprintf("id%03d", 1:K), N, TRUE), # large groups (char)
id2 = sample(sprintf("id%03d", 1:K), N, TRUE), # large groups (char)
id3 = sample(sprintf("id%010d", 1:(N/K)), N, TRUE), # small groups (char)
id4 = sample(K, N, TRUE), # large groups (int)
id5 = sample(K, N, TRUE), # large groups (int)
id6 = sample(N/K, N, TRUE), # small groups (int)
v1 = sample(5, N, TRUE), # int in range [1,5]
v2 = sample(5, N, TRUE), # int in range [1,5]
v3 = sample(round(runif(100, max = 100), 4), N, TRUE) # numeric e.g. 23.5749
)
microbenchmark(
DT2[, .(id1, id5)],
DT2[, c("id1", "id5")]
)
Unit: microseconds
expr min lq mean median uq max neval
DT2[, .(id1, id5)] 1405.042 1461.561 1525.5314 1491.7885 1527.8955 2220.860 100
DT2[, c("id1", "id5")] 614.624 640.617 666.2426 659.0175 676.9355 906.966 100
يمكنك إصلاح تنسيق منشورك باستخدام سطر واحد من ثلاث علامات خلفية قبل وبعد مقطع الرمز:
```
code
```
يتم احتسابها عندما يتعين عليّ تقسيم عدة جداول صغيرة بطريقة متكررة.
أعتقد أن اختيار الأعمدة بشكل متكرر من الجداول الصغيرة أمر يجب تجنبه ، وفي معظم الحالات يمكن تجنبه ...؟ نظرًا لأن j
in DT[i, j, by]
يدعم ويحسن مثل هذه المجموعة المتنوعة من المدخلات ، أعتقد أنه من الطبيعي أن يكون هناك بعض النفقات العامة في تحليلها.
فيما يتعلق بالطرق الأخرى للتعامل مع مشكلتك (وربما يكون هذا مناسبًا بشكل أفضل لـ Stack Overflow إذا كنت تريد التحدث عنها أكثر) ... اعتمادًا على ما تريد فعله بالجدول ، يمكنك فقط حذف العواميد الأخرى ، DT[, setdiff(names(DT), cols) := NULL]
واستمر في استخدام DT مباشرة.
إذا كنت لا تزال تفضل أخذ المجموعة الفرعية ، فإن الحصول على مؤشرات الأعمدة يكون أسرع بكثير من أي من الخيارين اللذين فكرت فيهما هنا ، على الرغم من أن التعديلات على النتيجة بهذه الطريقة ستؤثر على الجدول الأصلي:
library(data.table)
library(microbenchmark)
N <- 2e8
K <- 100
set.seed(1)
DT <- data.table(
id1 = sprintf("id%03d", 1:K), # large groups (char)
id2 = sprintf("id%03d", 1:K), # large groups (char)
id3 = sprintf("id%010d", 1:(N/K)), # small groups (char)
id4 = sample(K), # large groups (int)
id5 = sample(K), # large groups (int)
id6 = sample(N/K), # small groups (int)
v1 = sample(5), # int in range [1,5]
v2 = sample(5), # int in range [1,5]
v3 = round(runif(100, max = 100), 4), # numeric e.g. 23.5749
row = seq_len(N)
)
cols = c("id1", "id5")
microbenchmark(times = 3,
expression = DT[, .(id1, id5)],
index = DT[, c("id1", "id5")],
dotdot = DT[, ..cols],
oddball = setDT(lapply(setNames(cols, cols), function(x) DT[[x]]))[],
oddball2 = setDT(unclass(DT)[cols])[]
)
Unit: microseconds
expr min lq mean median uq max neval
expression 1249753.580 1304355.3415 1417166.9297 1358957.103 1500873.6045 1642790.106 3
index 1184056.302 1191334.4835 1396372.3483 1198612.665 1502530.3715 1806448.078 3
dotdot 1084521.234 1240062.2370 1439680.6980 1395603.240 1617260.4300 1838917.620 3
oddball 92.659 171.8635 568.5317 251.068 806.4680 1361.868 3
oddball2 66.582 125.9505 150.7337 185.319 192.8095 200.300 3
(لقد استبعدت العشوائية من مثالك وقللت # مرة في المعيار لأنني كنت غير صبور.)
لم أجد أبدًا طريقة للاتصال المباشر بالمجموعة الفرعية لقائمة R (والتي يتم استخدامها بعد unclass
أعلاه).
بخصوص "التعديلات على النتيجة ستعدل الجدول الأصلي" ، أعني:
myDT = data.table(a = 1:2, b = 3:4)
# standard way
res <- myDT[, "a"]
res[, a := 0]
myDT
# a b
# 1: 1 3
# 2: 2 4
# oddball, grabbing pointers
res2 <- setDT(unclass(myDT)["a"])
res2[, a := 0]
myDT
# a b
# 1: 0 3
# 2: 0 4
حسنًا ، لقد تعلمت شيئًا جديدًا وسريعًا (الكرات الغريبة) اليوم وقد لاحظت أن هناك مفاضلة بين السرعة والتشفير البخل. لذا فإن الكوب نصف ممتلئ! شكرا!
أعتقد # 852 ذات الصلة
التعليق الأكثر فائدة
يمكنك إصلاح تنسيق منشورك باستخدام سطر واحد من ثلاث علامات خلفية قبل وبعد مقطع الرمز:
أعتقد أن اختيار الأعمدة بشكل متكرر من الجداول الصغيرة أمر يجب تجنبه ، وفي معظم الحالات يمكن تجنبه ...؟ نظرًا لأن
j
inDT[i, j, by]
يدعم ويحسن مثل هذه المجموعة المتنوعة من المدخلات ، أعتقد أنه من الطبيعي أن يكون هناك بعض النفقات العامة في تحليلها.فيما يتعلق بالطرق الأخرى للتعامل مع مشكلتك (وربما يكون هذا مناسبًا بشكل أفضل لـ Stack Overflow إذا كنت تريد التحدث عنها أكثر) ... اعتمادًا على ما تريد فعله بالجدول ، يمكنك فقط حذف العواميد الأخرى ،
DT[, setdiff(names(DT), cols) := NULL]
واستمر في استخدام DT مباشرة.إذا كنت لا تزال تفضل أخذ المجموعة الفرعية ، فإن الحصول على مؤشرات الأعمدة يكون أسرع بكثير من أي من الخيارين اللذين فكرت فيهما هنا ، على الرغم من أن التعديلات على النتيجة بهذه الطريقة ستؤثر على الجدول الأصلي:
(لقد استبعدت العشوائية من مثالك وقللت # مرة في المعيار لأنني كنت غير صبور.)
لم أجد أبدًا طريقة للاتصال المباشر بالمجموعة الفرعية لقائمة R (والتي يتم استخدامها بعد
unclass
أعلاه).بخصوص "التعديلات على النتيجة ستعدل الجدول الأصلي" ، أعني: