2017-04-18 96 views
2

我在這個格式的CSV:創建並從現有列填充基於價值的數據幀新列

Col1_Status Col1_Value Col2_Status Col2_Value Col3_Status Col3__Value 
LOW    5   HIGH   5   LOW   5 
LOW    8   HIGH   8   LOW   8 
HIGH   82   HIGH   8   LOW   7 
HIGH   83   NORMAL  8   LOW   7 
HIGH   82   NORMAL  8   LOW   7 

我想創建一個具有高,低欄目,例如一個新的數據幀:

Col1_High Col1_Low Col2_High Col2_Low Col3_High Col3_Low 
    82   5  5  NA  NA  5 
    83   8  8  NA  NA  8 
    82   NA  8  NA  NA  7 
    NA   NA  NA  NA  NA  7 
    NA   NA  NA  NA  NA  7 

什麼是最好的方式去做這件事?

到目前爲止,我認爲:

#extract the Status Columns from original file into DataFrame 
    statusDF <- ret[grepl("Status", colnames(ret))] 

    #extract the Value Columns from original file into DataFrame 
    originalValueDF <- ret[grepl("Value", colnames(ret))] 

    #create new columns attribute_high and attribute_low 
    for(i in names(originalValueDF)){ 
    newValueDF <- originalValueDF[[paste(i, 'High', sep = "_")]] 
    newValueDF <- originalValueDF[[paste(i, 'Low', sep = "_")]] 
    } 

#populate both columns based on value in attribute status column 
for(i in names(originalValueDF)){ 
    if (originalValueDF$i == "High"){ 
     temp <- # stuck here 
    } 
    } 

任何建議表示讚賞

+0

'Col3_Low = C(5,8)'...其中是7?你的標準是什麼? – Sotos

+0

對不起,我只是把前兩個元組作爲所需的輸出。標準是查看狀態列並將其提取到高或低的新列中。 – ukbaz

+0

已更新輸出數據幀 – ukbaz

回答

1

這裏是一個有很多的lapply的嘗試。我們首先創建一個列表(l1),其中包含每個「高」和「低」狀態的值。但是,這些向量的長度是不同的,所以我們需要將它們全部設置爲等於它們的最大值(在本例中爲ind)。我們使用2列(高和低)將矢量轉換爲矩陣,並使用do.callcbind來獲得最終的數據幀。

l1 <- lapply(seq(1, ncol(df), by = 2), function(i) list(HIGH = df[i+1][df[i] == 'HIGH'], 
                 LOW = df[i+1][df[i] == 'LOW'])) 
names(l1) <- paste0('Col', seq(length(l1))) 

ind <- max(unlist(lapply(l1, function(i) lengths(i)))) 

do.call(cbind, lapply(lapply(l1, function(i) lapply(i, `length<-`, ind)), function(j) 
        setNames(data.frame(matrix(unlist(j), ncol = 2)), c('High', 'Low')))) 

# Col1.High Col1.Low Col2.High Col2.Low Col3.High Col3.Low 
#1  82  5   5  NA  NA  5 
#2  83  8   8  NA  NA  8 
#3  82  NA   8  NA  NA  7 
#4  NA  NA  NA  NA  NA  7 
#5  NA  NA  NA  NA  NA  7 
+0

非常感謝您,您是否介意解釋它 - 這似乎相當複雜 – ukbaz

0
ret <- read.table(text=" 
Col1_Status Col1_Value Col2_Status Col2_Value Col3_Status Col3__Value 
LOW    5   HIGH   5   LOW   5 
LOW    8   HIGH   8   LOW   8 
HIGH   82   HIGH   8   LOW   7 
HIGH   83   NORMAL  8   LOW   7 
HIGH   82   NORMAL  8   LOW   7 
", header = TRUE, stringsAsFactors = F) 

# fix column headers 
names(ret) <- gsub("(_+)", "_", names(ret)) 

library(stats) 

# extract the column prefixes 
prefixes <- unique(gsub("_.+", "", names(ret))) 
value_names <- names(ret[grepl("_Value", names(ret))]) 
status_names <- names(ret[grepl("_Status", names(ret))]) 

library(stats) 
# get the lwo values - extract the lows, pad with NA's and set the name to _High 
high_values <- sapply(1:length(prefixes), 
         function(i) { 
         result <- ret[which(ret[, status_names][i] == "HIGH"), value_names][[i]] 
         result[(length(result)+1):nrow(ret)+1] <- NA 
         setNames(list(foo = result[1:nrow(ret)]), paste0(prefixes[i], "_High"))}) 

# get the lwo values - extract the lows, pad with NA's and set the name to _Low 
low_values <- sapply(1:length(prefixes), 
         function(i) { 
         result <- ret[which(ret[, status_names][i] == "LOW"), value_names][[i]] 
         result[(length(result)+1):nrow(ret)+1] <- NA 
         setNames(list(foo = result[1:nrow(ret)]), paste0(prefixes[i], "_Low"))}) 

# combine 
output <- cbind(data.frame(low_values), data.frame(high_values)) 

output 

# Col1_Low Col2_Low Col3_Low Col1_High Col2_High Col3_High 
# 1  5  NA  5  82   5  NA 
# 2  8  NA  8  83   8  NA 
# 3  NA  NA  7  82   8  NA 
# 4  NA  NA  7  NA  NA  NA 
# 5  NA  NA  7  NA  NA  NA