循环遍历列并为每个记录R生成行

时间:2017-04-03 00:34:14

标签: r loops sas hierarchical-data

当我以前在SAS中编程时,很容易循环变量并在应用某种逻辑后生成行。我想在R中这样做。为了说明,请考虑以下情况。

Input
+----+----------------+-------------------+-------------+
| ID |      lvl1      |        lvl2       |     lvl3    |
+----+----------------+-------------------+-------------+
|  1 |  United States |  Ohio             |  Cincinnati |
|  2 |  Ohio          |  Cincinnati       |             |
|  3 |  Canada        |  British Columbia |  Vancouver  |
+----+----------------+-------------------+-------------+

让数组_lvl包含lvl1,lvl2和lvl3,并从i = 1到3循环(上限)。

  1. 循环1:_lvl(1)检查lvl1是否为空,否则输出,为其他值提供空值。
  2. 循环2:_lvl(2)检查lvl1是否为null或lvl2是否为空,如果没有则输出,为lvl3提供null。
  3. 循环3:_lvl(3)检查lvl1是否为null,lvl2为null,或者lvl3为null,否则输出。
  4. 这应该为ID = 2产生以下内容。

    Output
    +----+-------+-------------+-------+
    | ID |  lvl1 |     lvl2    |  lvl3 |
    +----+-------+-------------+-------+
    |  2 |  Ohio |             |       |
    |  2 |  Ohio |  Cincinnati |       |
    +----+-------+-------------+-------+
    

    提前谢谢。

2 个答案:

答案 0 :(得分:1)

以下是使用某些索引在适当情况下消除值的尝试:

newdat <- dat[rep(1:nrow(dat),each=3),]
newdat[-1][upper.tri(dat[-1])[rep(1:nrow(dat),3),]] <- ""
unique(newdat)

#    ID          lvl1             lvl2       lvl3
#1    1 United States                            
#1.1  1 United States             Ohio           
#1.2  1 United States             Ohio Cincinnati
#2    2          Ohio                            
#2.1  2          Ohio       Cincinnati           
#3    3        Canada                            
#3.1  3        Canada British Columbia           
#3.2  3        Canada British Columbia  Vancouver

这是有效的,因为创建的矩阵表示要删除newdat的部分:

upper.tri(dat[-1])[rep(1:nrow(dat),3),]
#       [,1]  [,2]  [,3]
# [1,] FALSE  TRUE  TRUE
# [2,] FALSE FALSE  TRUE
# [3,] FALSE FALSE FALSE
# [4,] FALSE  TRUE  TRUE
# [5,] FALSE FALSE  TRUE
# [6,] FALSE FALSE FALSE
# [7,] FALSE  TRUE  TRUE
# [8,] FALSE FALSE  TRUE
# [9,] FALSE FALSE FALSE

dat的位置:

dat <- read.csv(text="ID,lvl1,lvl2,lvl3    
1,United States,Ohio,Cincinnati
2,Ohio,Cincinnati,
3,Canada,British Columbia,Vancouver", stringsAsFactors=FALSE)

答案 1 :(得分:1)

我对你的特定用例并不太热衷,但我对以这种方式使用SAS数据步骤后调整为R的一般性努力表示同情。

我在R中的数据步骤中模拟输出语句的方法是沿数据框的行(或在本例中为列)应用函数。

定义列名称的“数组”:

lvl <- c('lvl1','lvl2','lvl3')

然后使用函数模拟SAS输出语句(i扮演与SAS数组索引相同的角色,data代表输入数据框,names是列名称的整个向量迭代):

outputcriteria <- function(i, data, names) {
  data <- data[!is.na(data[,names[i]]),] #exclude rows with NA in the current column
  data[,names[-(1:i)]] <- NA             #blank out columns after the current column
  return (data)
}

然后将此函数应用于df数据框lapply(),方法是将输入向量设置为1:length(lvl)(列名称向量的索引),并传递{{} 1}}和data参数进入函数:

name

结果l <- lapply(1:length(lvl), outputcriteria, data = df, names = lvl) 是三个数据框的列表(每次迭代一个),您可以l到一个数据框中:

rbind

主要区别在于您最终每次读取数据三次并输出数据帧,而不是在SAS中读取一次。