如何在 R 数据框中将所有列的数据向上或向下移位?

4
我有以下的 R 数据框:
df <- data.table(
  id = c(1, 2, 3),
  x = c(1, NA, NA),
  y = c(NA, 2, NA),
  z = c(NA, NA, 3))

我希望将“y”列以及其后所有列的数据向上移动,但不改变值顺序。列数是可变的。最终数据集应该如下所示:

df_result <- data.table(
  id = c(1, 2, 3),
  x = c(1, NA, NA),
  y = c(2, NA, NA),
  z = c(3, NA, NA))

如果您能帮忙,感激不尽!

谢谢。

4个回答

3

一种选择是在 NA 元素上进行 order - 使用 is.na 将列转换为逻辑型,返回存在 NAs 的为TRUE,不存在 NAs 的为FALSE。当我们在这个结果上进行 order 时,按照字母表顺序,TF 后面且位于最后,使用该索引进行重新排序。

library(data.table)
df[, (names(df)[-1]) := lapply(.SD, function(x)
     x[order(is.na(x))]), .SDcols = -1]

-输出

> df
      id     x     y     z
   <num> <num> <num> <num>
1:     1     1     2     3
2:     2    NA    NA    NA
3:     3    NA    NA    NA

这个代码给我一个错误提示:"错误:在 'df[, (names(df)[-1]) := lapply(.SD, " 中出现了意外输入。" - Andrii
@Andrii 我猜你的 R 版本比较旧。\(x) 是基础 R 中等同于新版本中的 function(x) 的表达方式。 - akrun
[.data.table(df1, , :=((names(df1)[-1]), lapply(.SD, function(x) x[order(is.na(x))])), : 提供了18列以分配3个项目。请参阅v1.12.2的NEWS。 - Andrii
是的。我需要这个适用于旧版本的 R。 - Andrii
1
终于可以了!非常感谢。我将这个答案标记为最佳答案! - Andrii
显示剩余5条评论

3

您可以使用order来将非'NA'值上移,而不改变顺序:

sapply(df, \(x) x[order(!is.na(x), decreasing = T)])
     id  x  y  z
[1,]  1  1  3  3
[2,]  2 NA  2 NA
[3,]  3 NA NA NA

数据:

df <- data.frame(
  id = c(1, 2, 3),
  x = c(1, NA, NA),
  y = c(3, 2, NA),
  z = c(NA, NA, 3))

这会改变列中值的顺序。顺序应该保持不变。 - Andrii
1
请查看编辑,这应该可以工作。 - Maël

2

这将把值向上移动,而不改变顺序

# Helper function
f <- function(x)  c(x[!is.na(x)], x[is.na(x)])

# Apply to each column
df[,(names(df)):=lapply(.SD,f)]

@Maël表明更好的方法是只调用is.na()一次,像这样:

f <- function(x)  x[order(!is.na(x),decreasing=T)]

1
@Maël 只调用了 is.na() 一次,做得很好。我已经在更新中记录了这一点。 - langtang

1

另一种解决您问题的方法:

library(data.table)

df[, Map(`[`, .SD, lapply(.SD,  \(x) order(as.logical(x))))]

      id     x     y     z
   <num> <num> <num> <num>
1:     1     1     2     3
2:     2    NA    NA    NA
3:     3    NA    NA    NA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接