繁体   English   中英

R中的SAS Array等价物

[英]SAS Array equivalent in R

我有一个包含以下列的数据集:

    ID  Measure1    Measure2    XO  X1  x2  x3  x4  x5
    1   30  2   item1   item1   item23  NA      item6   item9
    2   23  2   item1   item323 item1   item4   item5   NA      
    3   2   2   item1   item78  item3   NA      item1   item5

我想用R中的这段SAS代码创建一个标志变量:

 data dt2;
 set dt1;
 array x {5} x1 - x5;
 do i=1 to 5;
 if x0=x{i} then do; 
 flag=i;
 leave;
 end;
 end;
 drop i;
 run;

目标是能够浏览x1-x5的值,并查看xo等于其中任何一个并返回位置,例如,如果在x1找到item1,则返回到值1,如果在位置x3处找到则返回3。

最终产品看起来像这样:

    ID  Measure1    Measure2    XO  X1  x2  x3  x4  x5  Flag
    1   30  2   item1   item1   item23  NA          item6   item9   1
    2   23  2   item1   item323 item1   item4       item5   NA      2
    3   2   2   item1   item78  item3   NA          item1   item5   4

请记住,可能存在所有行x1-x5都包含NA的情况,在这种情况下我想返回空白,这可能吗?

我无法在R中找到与动态意义相同的东西(没有使用sqldf编写多个if语句或大小写)因为现在列可能是5但可以在将来改为最多20。

有任何想法吗?

我们可以使用max.col

df1$Flag <- max.col(df1$XO[row(df1[-1])]==df1[-1], 'first')
df1
#    XO      X1     x2     x3    x4    x5 Flag
#1 item1   item1 item23  item5 item6 item9    1
#2 item1 item323  item1  item4 item5 itm87    2
#3 item1  item78  item3 item98 item1 item5    4

更新

基于更新的数据集,我们可以用FALSE替换逻辑矩阵中的NA元素,然后使用max.col 如果一行中没有TRUE值,我们可以通过获取rowSums将其设为NA ,检查它是否为0,将值更改为0到NA( NA^.. )并乘以max.col(.

df3 <- df2[5:ncol(df2)]
i1 <- df2$XO[row(df3)]==df3
i2 <- replace(i1, is.na(i1), FALSE)
df2$Flag <- max.col(i2, 'first') * NA^(rowSums(i2)==0)
df2
#  ID Measure1 Measure2    XO      X1     x2    x3    x4    x5 Flag
#1  1       30        2 item1   item1 item23  <NA> item6 item9    1
#2  2       23        2 item1 item323  item1 item4 item5  <NA>    2
#3  3        2        2 item1  item78  item3  <NA> item1 item5    4

1)base R as.matrix(DF[5:9]) == XO产生一个与DF[5:9]具有相同尺寸的逻辑矩阵。 wm应用于每一行。 wmwhich.max相同,除了它在没有TRUE值的情况下返回NA ,即如果一行中只有NA和FALSE值。 如果没有这种情况,那么我们可以使用which.max代替wm将解决方案减少到单行。 如果一行中有多个TRUE值,它将使用第一个。

wm <- function(x) if (isTRUE(any(x))) which.max(x) else NA
transform(DF, Flag = apply(as.matrix(DF[-(1:4)]) == XO, 1, wm))

赠送:

  ID Measure1 Measure2    XO      x1     x2    x3    x4    x5 Flag
1  1       30        2 item1   item1 item23  <NA> item6 item9    1
2  2       23        2 item1 item323  item1 item4 item5  <NA>    2
3  3        2        2 item1  item78  item3  <NA> item1 item5    4

2)dplyr / tidyr这里的主要复杂性是数据没有规范化,而是x1,...,xn列以宽泛的形式写出。 为了解决这个问题,我们可以使用tidyr的gather将数据帧转换为长格式,检查项目是否等于XO并加入到原始数据框:

library(dplyr)
library(tidyr)
DF %>% 
   left_join(DF %>% gather(Flag, item, -(1:4)) %>% filter(item == XO)) %>%
   select(-item) %>%
   mutate(Flag = match(Flag, names(DF)[-(1:4)]))

赠送:

  ID Measure1 Measure2    XO      X1     x2    x3    x4    x5 Flag
1  1       30        2 item1   item1 item23  <NA> item6 item9    1
2  2       23        2 item1 item323  item1 item4 item5  <NA>    2
3  3        2        2 item1  item78  item3  <NA> item1 item5    4

3)另一种基础解决方案这种基础解决方案的灵感来自dplyr / tidyr解决方案。 它使用reshape将原始数据帧转换为长格式,它选取相等的行,然后将Flag变量合并到原始数据帧:

r <- reshape(DF, list(names(DF)[-(1:4)]), "X", "Flag", direction = "long")
s <- subset(r, X == XO)[c("ID", "Flag")]
merge(DF, s, all.x = TRUE)

赠送:

  ID Measure1 Measure2    XO      X1     x2    x3    x4    x5 Flag
1  1       30        2 item1   item1 item23  <NA> item6 item9    1
2  2       23        2 item1 item323  item1 item4 item5  <NA>    2
3  3        2        2 item1  item78  item3  <NA> item1 item5    4

注意:为了使这个可重现,我们提供了在下面创建输入的代码。 下次请自己提供。

Lines <- "  ID  Measure1    Measure2    XO  x1  x2  x3  x4  x5
    1   30  2   item1   item1   item23  NA      item6   item9
    2   23  2   item1   item323 item1   item4   item5   NA      
    3   2   2   item1   item78  item3   NA      item1   item5"

DF <- read.table(text = Lines, header = TRUE, as.is = TRUE)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM