基于数据框中的多个列进行变异

时间:2018-02-28 01:36:58

标签: r dataframe dplyr tidyr

好的,所以我的数据框看起来像是df

KEY   A1  A2  A3 A4  B1 B2 B3 B4 C1  C2  C3  C4
1     120 100 NA 110 1  1  NA  1  NA NA NA NA
2     100 NA 115 NA  NA NA NA NA  Y  N   Y N

所以我要做的就是让A柱的值为100,相应的B或C列的值分别为1或“Y”,这样就可以生成一个带X的新列值为1.在第1行中为A2和B2,在行中为A1和C1。

我尝试了三组聚集,然后使用case_when使用mutate函数。像这样

df<- df %>%
  gather(key="A",value="code",dx)%>%
  gather(key="B",value="number",dxadm)%>%
  gather(key="C",value="character",dxpoa) %>%
  mutate(X=case_when(
    code == 100 & present >0 ~ 1,
    code ==100 & character == "Y"~1)
  )

除了我的这些行的传播函数,所有数组和我的X都不在行。

或者,我考虑过像

这样的东西
df <- df %>%
mutate(X=case_when(
    A1 == 100 & B1 >0 ~ 1,
    A1 ==100 & C1 == "Y"~1,
    A2 == 100 & B2 >0 ~ 1,
    A2 ==100 & C2 == "Y"~1,) 
所有排列的

等等。这个问题的两个问题是我有很多专栏,而且我希望这个有多个不同的A值。

任何人都可以推荐一种替代方法,或者至少是一种方法,将第二种解决方案变成一种只需要一段烦人的长代码的东西,我可以将它变成一种更通用的功能吗?谢谢!

3 个答案:

答案 0 :(得分:2)

建议

require(read.so) #awesome package to read from Stackoverflow, 
# available on GitHub [https://alistaire47.github.io/read.so/][1]
require(tidyr)
require(reshape2)
require(dplyr)

dat <- read.so()    

dat %>% gather(var, value, 2:13) %>% #make it long
  mutate(var = gsub('([A-Z])', '\\1_', .[['var']])) %>% #add underscore
  separate(var, c('var', 'number') ) %>% #separate your column 
  dcast(KEY+number ~ var) %>% #dcast is a bit complex but quite powerful
  group_by(KEY) %>% 
  filter(A == 100) 

# A tibble: 2 x 5
# Groups:   KEY [2]
    KEY number A     B     C    
  <int> <chr>  <chr> <chr> <chr>
1     1 2      100   1     <NA> 
2     2 1      100   <NA>  Y  

答案 1 :(得分:2)

使用的解决方案。我们可以gatherKEY之外的所有列,separate字母和数字,然后spread字母,以便我们可以创建X列,而无需指定数字。请注意,我假设如果不满足条件,X将是0,并且根据您的描述,我使用any(A %in% 100 & (B %in% 1 | C %in% "Y"))来测试条件,因为任何给定的数字都符合条件,{ {1}}将是X

1

我认为library(dplyr) library(tidyr) df2 <- df %>% gather(Column, Value, -KEY) %>% separate(Column, into = c("Letter", "Number"), sep = 1) %>% spread(Letter, Value, convert = TRUE) %>% group_by(KEY) %>% mutate(X = ifelse(any(A %in% 100 & (B %in% 1 | C %in% "Y")), 1L, 0L)) df2 %>% as.data.frame() # KEY Number A B C X # 1 1 1 120 1 <NA> 1 # 2 1 2 100 1 <NA> 1 # 3 1 3 NA NA <NA> 1 # 4 1 4 110 1 <NA> 1 # 5 2 1 100 NA Y 1 # 6 2 2 NA NA N 1 # 7 2 3 115 NA Y 1 # 8 2 4 NA NA N 1 的结构很好,但如果你真的想要原始结构,我们可以做到以下几点。

df2

df3 <- df2 %>% gather(Letter, Value, A:C) %>% unite(Column, Letter, Number, sep = "") %>% spread(Column, Value) %>% select(names(df), X) df3 %>% as.data.frame() # KEY A1 A2 A3 A4 B1 B2 B3 B4 C1 C2 C3 C4 X # 1 1 120 100 <NA> 110 1 1 <NA> 1 <NA> <NA> <NA> <NA> 1 # 2 2 100 <NA> 115 <NA> <NA> <NA> <NA> <NA> Y N Y N 1 是最终输出。

数据

df3

答案 2 :(得分:2)

与Tjebo一样的想法,但坚持整齐[....]

library(tidyverse)

dat <- data.frame(stringsAsFactors=FALSE,
         KEY = c(1L, 2L),
          A1 = c(120L, 100L),
          A2 = c(100L, NA),
          A3 = c(NA, 115L),
          A4 = c(110L, NA),
          B1 = c(1L, NA),
          B2 = c(1L, NA),
          B3 = c(NA, NA),
          B4 = c(1L, NA),
          C1 = c(NA, "Y"),
          C2 = c(NA, "N"),
          C3 = c(NA, "Y"),
          C4 = c(NA, "N"))

dat %>% 
  gather(var, value, -KEY) %>% #make it long
  extract(var, regex = "(.)(.)", into = c("var", "number") ) %>% 
  spread(var, value) %>% 
  filter( A %in% 100 )

#>   KEY number   A    B    C
#> 1   1      2 100    1 <NA>
#> 2   2      1 100 <NA>    Y

reprex package(v0.2.0)创建于2018-02-27。