2017-02-23 24 views
0

我有一個有幾行的數據集。在一行內切換值

x1 x2 x3 x4 x5 y1 y2 y3 y4 y5 
1 3 2 1 5 0.2 0.1 0.1 0.4 0.2 
1 2 4 2 4 -1 -1 -1 -1 -1 
4 4 1 2 4 0.2 0.2 0.3 0.1 0.9 

-1實際上只是一個任意值,表示缺少某些東西。

我想將-1y列是要在x列切換:

x1 x2 x3 x4 x5 y1 y2 y3 y4 y5 
1 3 2 1 5 0.2 0.1 0.1 0.4 0.2 
-1 -1 -1 -1 -1 1 2 4 2 4 ###Changed row 
4 4 1 2 4 0.2 0.2 0.3 0.1 0.9 

這僅僅是一個示例數據集;問題是我有超過30個數據集,每個數據集都有1000多行數據,這種情況發生在幾個地方。我知道有一種方法可以通過斬斷整個數據集並切換值來做到這一點,但我想知道在大數據集中是否有更好的方法來處理它,例如使用for循環?

+0

你在每組中只有2個不同的(x,y)組的列嗎? – Sotos

+0

像這樣編號的列使得大多數操作更難。您應該將數據幀重新整理爲長格式(查看包)。這使得這個操作變得微不足道。 –

+0

在某些情況下,適合這個例子,你可以使用'df [df $ y1 <0,] < - df [df $ y1 <0,c(6:10,1:5)]'。 – lmo

回答

1

一種替代的解決方案:

library(dplyr) 

#Example dataframe 
df <- data.frame(
    matrix(round(runif(15,min = 0,max=5),digits = 0),ncol = 5), 
    matrix(round(runif(15,min = 0,max=1),digits = 1),ncol = 5,dimnames = list(NULL,paste0('y',1:5))) 
) 
df[2,6:10] <- -1 

switcher_function <- function(d){ 
    d <- data.frame(t(d)) 
    df.y <- d %>% select(contains('y')) 
    df.x <- d %>% select(contains('x')) 
    if(sum(df.y)==-1*ncol(df.y)){ 
    return(as.numeric(cbind(df.y[1,],df.x[1,]))) 
    }else{ 
    return(as.numeric(cbind(df.x[1,],df.y[1,]))) 
    } 
} 

want <- t(apply(X = df,MARGIN = 1,FUN = switcher_function)) 
+0

應該是'df [2,6:10] < - -1' – manotheshark

+0

@manotheshark同意。固定。 – Rahul

0

下面是使用基礎R的想法,因爲你只有2個不同組的列(x和y),那麼,

ind1 <- t(apply(df2, 1, function(i)mapply(function(x, y) 
      replace(x, all(y == -1), y), i[grepl('x', names(i))], i[grepl('y', names(i))]))) 

ind2 <- t(apply(df2, 1, function(i)mapply(function(x, y) 
      replace(x, all(x == -1), y), i[grepl('y', names(i))], i[grepl('x', names(i))]))) 

final_df <- as.data.frame(cbind(ind1, ind2)) 

final_df 
# x1 x2 x3 x4 x5 y1 y2 y3 y4 y5 
#1 1 3 2 1 5 0.2 0.1 0.1 0.4 0.2 
#2 -1 -1 -1 -1 -1 1.0 2.0 4.0 2.0 4.0 
#3 4 4 1 2 4 0.2 0.2 0.3 0.1 0.9 
0

In tidy data format,您的表將如下所示:

 i  x  y 
1  1  1 0.2 
2  1  1 -1.0 
3  1  4 0.2 
4  2  3 0.1 
5  2  2 -1.0 
6  2  4 0.2 
7  3  2 0.1 
8  3  4 -1.0 
9  3  1 0.3 
10  4  1 0.4 
11  4  2 -1.0 
12  4  2 0.1 
13  5  5 0.2 
14  5  4 -1.0 
15  5  4 0.9 

鑑於這種格式,這是微不足道的(...)交換細胞Wh是ERE的y爲負:

mutate_when(df, y < 0, x = y, y = x) 

此使用 延伸( mutate_when)與 its code available as a Github Gist

另外,您可以用做同樣的剛 ,但它是一個比較複雜一點:

do(tibble(x = ifelse(.$y < 0, .$y, .$x), 
      y = ifelse(.$y < 0, .$x, .$y), 
      i = .$i)) 

這是使用tibble從包同名,並do 。可能有更好的方法 - 我只是不知道。

...但讓你的表格變得整潔的格式,並且在轉換之後,退出整齊格式稍微複雜一些。這裏是改造成整齊的數據:

tidy_df = df %>% 
    gather(name, value) %>% 
    mutate(i = as.integer(sub('x|y', '', name)), 
      name = sub('\\d', '', name)) %>% 
    group_by(name, i) %>% 
    mutate(row = row_number()) %>% 
    ungroup() %>% 
    spread(name, value) 

(這增加了一個額外的列保留在原始表中的行索引轉換回來以後如果這是沒有必要的,那麼無論是指數。)

現在我們可以執行交換...

tidy_df_swapped = tidy_df %>% 
    mutate_when(y < 0, x = y, y = x) 

其改造後的背部看起來是這樣的:

df_swapped = tidy_df_swapped %>% 
    gather(name, value, -i, -row) %>% 
    mutate(name = paste0(name, i)) %>% 
    select(-i) %>% 
    spread(name, value) %>% 
    select(-row) 
0

這是一個矩陣解決方案,因爲它沒有指定如何存儲數據。我也改變了-1NA因爲有人說這是一個任意選擇

m1 <- structure(c(1, 1, 4, 3, 2, 4, 2, 4, 1, 1, 2, 2, 5, 4, 4, 0.2, NA, 0.2, 0.1, NA, 0.2, 0.1, NA, 0.3, 0.4, 2, NA, 0.2, NA, NA), 
       .Dim = c(3L, 10L), 
       .Dimnames = list(NULL, c("x1", "x2", "x3", "x4", "x5", "y1", "y2", "y3", "y4", "y5"))) 

ind <- is.na(m1[, paste0("y", 1:5)]) 
m1[ind] <- c(tail(m1[ind], length(m1[ind])/2), head(m1[ind], length(m1[ind])/2)) 

提供一些速度比較(並保存微秒!)

Unit: microseconds 
       min  lq  mean median  uq  max neval 
    matrix 47.940 64.8710 89.9407 86.939 98.734 165.126 100 
final_df 704.258 742.3055 986.9160 791.767 1057.909 4310.011 100 
    want 3647.605 3982.4225 5184.6407 4410.836 6450.177 15161.132 100 

有可能是換一個更優雅的方式在第二步中的數組,但這是我現在得到的。