2017-01-04 4 views
2

私のデータフレームです:更新ペア

col_1
col_1 <- c(1,2,NA,4,5) 
temp_col_1 <-c(12,2,2,3,4) 
col_2 <- c(1,23,423,NA,23) 
temp_col_2 <-c(1,2,23,4,5) 

df_test<-data.frame(col_1,temp_col_1,col_2, temp_col_2) 

私はtemp_col_1から対応する値とNAを交換し、col_2temp_col_2

のために同じことをやりたいです

私は手動でifelseステートメントでそれを行う方法を知っています、問題は、私はパターンcol_nametemp_col_nameとトンの列を持っていると私はそれをどのように自動化することができますか。

df_test[,paste('temp_','col_1]のような別のものを試しましたが、何も機能しませんでした。 提案がありますか?

答えて

2
# list of columns we need to check for NA's 
col.to.check <- colnames(df_test)[!grepl("^temp", colnames(df_test))] 
# these columns need not be checked 
col.to.keep <- colnames(df_test)[grepl("^temp", colnames(df_test))] 

func <- function(x){ 
    y <- which(is.na(df_test[[x]]))  # which position do NA's exist 
    z <- df_test[[paste0("temp_", x)]][y] # which to be used to replace 
    df_test[[x]][y] = z     # replace them 
    return(df_test[[x]]) 
    } 

df = data.frame(lapply(col.to.check, func)) 
colnames(df) = col.to.check 
cbind(df, df_test[col.to.keep]) 

# col_1 col_2 temp_col_1 temp_col_2 
#1  1  1   12   1 
#2  2 23   2   2 
#3  2 423   2   23 
#4  4  4   3   4 
#5  5 23   4   5 
2

これは、あなたが望むものを提供するはずです。

col_1 <- c(1,2,NA,4,5) 
temp_col_1 <-c(12,2,2,3,4) 
col_2 <- c(1,23,423,NA,23) 
temp_col_2 <-c(1,2,23,4,5) 

df_test<-data.frame(col_1,temp_col_1,col_2, temp_col_2) 

temp_cols <- names(df_test)[grepl("^temp", names(df_test))] 
cols <- sub("^temp_", "", temp_cols) 

for (i in seq_along(temp_cols)){ 
    row_to_replace <- which(is.na(df_test[[cols[i]]])) 
    df_test[[cols[i]]][row_to_replace] <- df_test[[temp_cols[i]]][row_to_replace] 
} 

df_test 

    col_1 temp_col_1 col_2 temp_col_2 
1  1   12  1   1 
2  2   2 23   2 
3  2   2 423   23 
4  4   3  4   4 
5  5   4 23   5 

この質問は楽しいです。

lapply(names(df_test)[grepl("^temp_", names(df_test)], 
     function(tc){ 
     col <- sub("^temp_", "", tc) 
     row_to_replace <- which(is.na(df_test[[col]])) 
     df_test[[col]][row_to_replace] <<- df_test[[tc]][row_to_replace] 
     }) 

が、それはそれほど普及していない<<-演算子を使用する必要があります:私はそれがあるために作ってみた最もコンパクトなアプローチ。カラムは、一貫した順序で対になっている場合

+0

私はこれらの手順に従っていても、 'assign()'を強制的に ''に適用しました。'lapply()'の内部で行われた変更を反映するために、 'Globalenv'を使用します。あなたの '<< - 'でも同じことが起こりました。私たちよりも良い方法がありますか? –

+0

これは、実際にはforループが最適なオプションであるという壮大なケースだと思います。私は昨日これについても興味があり、将来の参考になるよう要点をまとめました。 https://gist.github.com/nutterb/f05cc0e725ed389292116eb661f68bb5誰かが 'for'ループの速度を上回ることができるかどうかを確認するために、より大きなデータセットで新しい質問を開くことを考えています。 – Benjamin

+0

素晴らしい!この場合、 'list2env()'助けをすることができますか? –

1

、あなたの例のように、あなたが試みることができる:

1A

ix <- which(is.na(df_test), arr.ind = TRUE) 
ix2 <- ix 
ix2[ , 2] <- ix2[ , 2] + 1 
df_test[ix] <- df_test[ix2] 

または:

図1b

d1 <- df_test[ , c(TRUE, FALSE)] 
d2 <- df_test[ , c(FALSE, TRUE)] 
d1[is.na(d1)] <- d2[is.na(d1)] 
d1 

あなたは、列のペアを持っていますが、必ずしも配置さではうまく、上記のような対毎の自分の名前で列を注文して起動した場合:

df <- data.frame(temp_col_2, col_1, col_2, temp_col_1) 
df <- df[ , order(names(df))] 

2A

ix <- which(is.na(df), arr.ind = TRUE) 
ix2 <- ix 
ix2[ , 2] <- ix2[ , 2] + ncol(df)/2 
df[ix] <- df[ix2] 

または:

2b

d1 <- df[ , 1:(ncol(df)/2)] 
d2 <- df[ , (ncol(df)/2 + 1):ncol(df)] 

その後図1bのように進みます。


一般的に、長い形式のデータを扱う方が便利だと思う傾向があります。ここにはdata.table機能を使用する可能性があります。

# melt data to long format 
d <- melt(setDT(df_test), measure = patterns("^col", "^temp"), value.name = c("col", "temp")) 

# update relevant values of 'col' 
d[is.na(col), col := temp] 

# if desired, cast back to wide format 
dcast(d, rowid(variable) ~ variable, value.var = c("col", "temp")) 
関連する問題