如何在条件允许的情况下提高累计和重置的性能?
我有一个public void uploadNotesToSTORAGE(final ArrayList<NoteItem> nItems, final Activity activity) {
final ProgressDialog dialog = new ProgressDialog(activity);
dialog.setMessage("Uploading picture...");
dialog.show();
for (int i = 0; i < nItems.size(); i++) {
final String id = Calendar.getInstance().getTimeInMillis() + "";
StorageReference reference = mStorageRef.child("notes/" + id);
String filePath = nItems.get(i).getFilePath();
final int finalI = i;
final int finalI1 = i;
reference.putFile(Uri.fromFile(new File(filePath))).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
StorageReference reference = mStorageRef.child("notes/" + id);
reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri dUri) {
nItems.get(finalI).setId(id);
nItems.get(finalI).setDownloadLink(dUri + "");
db.collection("notes").document().set(nItems.get(finalI))
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(activity, "Successfully uploaded : " + nItems.get(finalI1).getFileName(), Toast.LENGTH_SHORT).show();
}
});
}
});
}
}).addOnFailureListener(onFailureListener);
dialog.dismiss();
activity.finish();
activity.startActivity(new Intent(activity, MainActivity.class));
}
}
,并在变量名data.frame
下附加了一个演示数据集。我有一列带有demo
的列,该列指出系统发生故障,然后列flag
计数该故障连续发生了多少次,并在故障恢复后重置。我正在使用tidyverse软件包,也使用了R。
我一直在阅读有关此问题的一些StackOverflow帖子,但是我似乎无法将思路用tidyverse和/或base R更快地解决。我已经使用for实现了该版本循环,但是对于较大的数据集,计算时间花费的时间过长(对于107388行数据帧,则为9分钟)。有没有更有效的解决方案来解决这个问题?
测试数据集:
continuousfailure
我当前使用的代码是:
demo <- data.frame(data = rnorm(100, mean = 0, sd = 2000), flag = c(rep(FALSE, 5), rep(TRUE, 10), rep(FALSE, 25), rep(TRUE, 23), rep(FALSE, 13), rep(TRUE, 5), rep(FALSE, 19)),
continuousfailure = c(rep(0, 5), 1:10, rep(0, 25), 1:23, rep(0, 13), 1:5, rep(0, 19)),magnitude = NA)
期望的输出预期是相同的,但是使用tidyverse或基数R可以提高函数的速度,通过对逻辑的构造方式的一些解释,也将不胜感激。
谢谢!
答案 0 :(得分:2)
我们可以使用data.table
rleid
创建组并根据cumsum
返回NA
或flag
library(dplyr)
demo %>%
group_by(group = data.table::rleid(flag)) %>%
mutate(new_mag = if(first(flag)) cumsum(data) else NA) %>%
ungroup %>%
select(-group)
# data flag continuousfailure magnitude new_mag
# <dbl> <lgl> <dbl> <dbl> <dbl>
# 1 -1121. FALSE 0 NA NA
# 2 -460. FALSE 0 NA NA
# 3 3117. FALSE 0 NA NA
# 4 141. FALSE 0 NA NA
# 5 259. FALSE 0 NA NA
# 6 3430. TRUE 1 3430. 3430.
# 7 922. TRUE 2 4352. 4352.
# 8 -2530. TRUE 3 1822. 1822.
# 9 -1374. TRUE 4 448. 448.
#10 -891. TRUE 5 -443. -443.
# … with 90 more rows
其中magnitude
是具有for
循环中的值的列,而new_mag
是上面代码的输出。
有多种创建组的方法。如上所示,一个使用rleid
,另一个使用lag
和dplyr
cumsum
group_by(group = cumsum(flag != lag(flag, default = first(flag)))) %>%
和另一个base
rle
group_by(group = with(rle(flag), rep(seq_along(lengths), lengths)))
您可以用以上任何一项替换group_by
行。
数据
set.seed(123)
demo <- data.frame(data = rnorm(100, mean = 0, sd = 2000),
flag = c(rep(FALSE, 5), rep(TRUE, 10), rep(FALSE, 25), rep(TRUE, 23),rep(FALSE, 13),
rep(TRUE, 5), rep(FALSE, 19)),continuousfailure = c(rep(0, 5), 1:10, rep(0, 25),
1:23, rep(0, 13), 1:5, rep(0, 19)),magnitude = NA)
答案 1 :(得分:0)
我们可以使用data.table
方法
library(data.table)
setDT(demo)[, new := if(first(flag)) cumsum(data) else NA_real_, rleid(flag)]
set.seed(123)
demo <- data.frame(data = rnorm(100, mean = 0, sd = 2000),
flag = c(rep(FALSE, 5), rep(TRUE, 10), rep(FALSE, 25), rep(TRUE, 23),rep(FALSE, 13),
rep(TRUE, 5), rep(FALSE, 19)),continuousfailure = c(rep(0, 5), 1:10, rep(0, 25),
1:23, rep(0, 13), 1:5, rep(0, 19)),magnitude = NA)