如何在R中“逐行”而不是列式地“融化”?

时间:2016-08-26 14:47:21

标签: r dataframe melt

我有一个数据框A,我希望以行方式而不是列方式融化,看起来像B(这也排除了NA中的观察结果)。这可以通过“融化”功能来实现吗?

A <- read.table(text="  Id1 Id2 Var1    Var2    Var3    
            1   1   1   2   NA  
            1   2   NA  3   4   
            1   3   5   6   7   ", header=T)


B <- read.table(text="  Id1 Id2 NewVar  
    1   1   1   
    1   1   2   
    1   2   3   
    1   2   4   
    1   3   5   
    1   3   6   
    1   3   7   ", header=T)

我找到一个类似问题的answer,但功能似乎有点矫枉过正,超出了我目前的R技能。

3 个答案:

答案 0 :(得分:5)

从tidyverse,融化 - &gt;总结 - &gt; UNNEST

library(reshape2)
library(tidyr)
melt(A, id=c("Id1", "Id2")) %>% group_by(Id1, Id2) %>%
  summarise(value=list(value[!is.na(value)])) %>% unnest()
# Source: local data frame [7 x 3]
# Groups: Id1 [1]
# 
#     Id1   Id2 value
#   <int> <int> <int>
# 1     1     1     1
# 2     1     1     2
# 3     1     2     3
# 4     1     2     4
# 5     1     3     5
# 6     1     3     6
# 7     1     3     7

修改

由于melt有一个NA删除参数(credit:@Frank),所以一行代码就可以了。注意:这一行是akrun的data.table方法的reshape2版本:

melt(A, id=c("Id1", "Id2"), na.rm=TRUE)[-3]

答案 1 :(得分:3)

order之后我们可以melt

library(data.table)
melt(setDT(A), id.var = c("Id1", "Id2"), na.rm = TRUE, value.name = "NewVar"
     )[order(Id1, Id2)][, variable := NULL][]
#   Id1 Id2 NewVar
#1:   1   1     1
#2:   1   1     2
#3:   1   2     3
#4:   1   2     4
#5:   1   3     5
#6:   1   3     6
#7:   1   3     7

或者我们可以通过复制扩展“A&#39;”行来base R。对于“Id&#39;列和cbind与非Id列的转置连接。

`row.names<-`(na.omit(data.frame(A[rep(1:nrow(A), each =3), 1:2], 
                    NewVar= c(t(A[-(1:2)])))), NULL)
#  Id1 Id2 NewVar
#1   1   1      1
#2   1   1      2
#3   1   2      3
#4   1   2      4
#5   1   3      5
#6   1   3      6
#7   1   3      7

答案 2 :(得分:2)

您可以将dplyrgather包中的tidyr一起使用:

library(dplyr)
library(tidyr)
A %>% gather(Key,NewVar,Var1:Var3) %>% 
      filter(!is.na(NewVar)) %>% 
      arrange(Id1,Id2) %>% select(-Key)
##  Id1 Id2 NewVar
##1   1   1      1
##2   1   1      2
##3   1   2      3
##4   1   2      4
##5   1   3      5
##6   1   3      6
##7   1   3      7

这会将列Var1:Var3收集到NewVar列中的行中。 Key列将包含所收集列的名称,这在最终结果中是不需要的。收集后filter NA NewVarID1。然后按ID2排序,然后按Key排序,并移除 Import-Csv C:\Users\drives.csv | Foreach-Object{ $user = ([ADSISEARCHER]"(samaccountname=$($_.SamAccountName))").FindOne() if($user) { New-Object -TypeName PSObject -Property @{ SamAccountName = $user.SamAccountName IsDisabled = $user.GetDirectoryEntry().InvokeGet('AccountDisabled') } } else { New-Object -TypeName PSObject -Property @{ SamAccountName = $user.SamAccountName IsDisabled = 'not found' } } } | export-csv myNew.csv -Append -NotypeInformation 列。