首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为每一列减去最小值--将减去的值添加到df中的另一列。

为每一列减去最小值--将减去的值添加到df中的另一列。
EN

Stack Overflow用户
提问于 2018-06-11 15:17:08
回答 1查看 1.3K关注 0票数 1

我有一份数据如下:

代码语言:javascript
复制
date    group    col1    col2    col3     col4     col5      
1234        1      -2       3       4       -5      100       
1235        1       4       5      -2       -7      200       
1234        1      -5       2       9        1      400       
1235        1       8       2      -4        7      900       
1235        2     -72      83     -54       98      800      
1233        2      32     -21      -1        4      900      
1342        2     -54       0     -10      -11      100      
1234        2      98      -8      -9      -10      100      

以下是我想做的事:

对于df列,从第2列到最后一栏,我想做以下操作:

1)每列按组取正数的最小值和负数的最小数。

2)然后使用此逻辑替换当前值:

a)如果值为正,则按组减去为正数找到的最小值。

b)如果数值为负值,则按组减去为负数找到的最小值。

( c)如果值为0,则不作任何更改。

3)然后取该行中的每个值减去的值,并将其添加到最后一列值中。

代码语言:javascript
复制
Minimum for col1 neg, group 1 = -5
Minimum for col1 pos, group 1 = 4
Minimum for col1 neg, group 2 = -72
Minimum for col1 pos, group 2 = 32
Minimum for col2 neg, group 1 = NA
Minimum for col2 pos, group 1 = 2
etc.  

我希望我的最后输出如下所示:

代码语言:javascript
复制
date    group         col1      col2      col3          col4            col5      
1234        1      -2-(-5)       3-2       4-4       -5-(-7)            100+(-5)+2+4+(-7)       
1235        1         4-4        5-2   -2-(-4)       -7-(-7)            200+4+2+(-4)+(-7)      
1234        1      -5-(-5)       2-2       9-4           1-1               400+(-5)+2+4+1       
1235        1         8-4        2-2   -4-(-4)           7-1               900+4+2+(-4)+1       
1235        2    -72-(-72)     83-83 -54-(-54)          98-4         800+(-72)+83+(-54)+4      
1233        2       32-32  -21-(-21)  -1-(-54)           4-4         900+32+(-21)+(-54)+4      
1342        2    -54-(-72)       0-0 -10-(-54)     -11-(-11)      100+(-72)+0+(-54)+(-11)      
1234        2       98-32   -8-(-21)  -9-(-54)     -10-(-11)     100+32+(-21)+(-54)+(-11) 

预期产出:

代码语言:javascript
复制
date    group         col1      col2      col3          col4            col5      
1234        1            3         1         0             2              94       
1235        1            0         3         2             0             195      
1234        1            0         0         5             0             402       
1235        1            4         0         0             6             903       
1235        2            0         0         0            94             761      
1233        2            0         0        53             0             861      
1342        2           18         0        44             0             -37      
1234        2           66        13        45             1              46
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-11 15:22:01

按'col1‘分组后,将’col1‘列用正负数的min值表示为'col4’,然后将数字的行和与'col5‘相加,并更新'col5’。稍后,将“col1”更新为“col4”,方法是从初始数据集的相应列(“df1”)中减去

代码语言:javascript
复制
library(dplyr)
df2 <- df1 %>%
  group_by(group) %>%
  mutate_at(3:6, 
   funs(case_when(. < 0  ~ if(any(. < 0)) as.numeric(min(.[. <0])) else NA_real_,
              . > 0 ~ if(any(. > 0)) as.numeric(min(.[. > 0])) else NA_real_, 
                           TRUE ~ as.numeric(.)))) %>%
   ungroup %>%                        
   mutate(col5 = col5 + rowSums(.[3:6])) 

nm1 <- paste0("col", 1:4)
#nm1 <- 3:6
df2[nm1] <- df1[nm1] - df2[nm1]
df2
# A tibble: 8 x 7
#   date group  col1  col2  col3  col4  col5
#  <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#1  1234     1     3     1     0     2    94
#2  1235     1     0     3     2     0   195
#3  1234     1     0     0     5     0   402
#4  1235     1     4     0     0     6   903
#5  1235     2     0     0     0    94   761
#6  1233     2     0     0    53     0   861
#7  1342     2    18     0    44     0   -37
#8  1234     2    66    13    45     1    46

或者使用parse_exprs进行修改

代码语言:javascript
复制
library(rlang)
expr <- paste(glue::glue('{nm1} - {nm1}_new'), collapse=";")
df1 %>% 
   group_by(group) %>%
   mutate_at(3:6, funs(new = ave(., sign(.), FUN = min))) %>%
   ungroup %>%
   mutate(col5 = col5 + select(., col1_new:col4_new)  %>% 
                    reduce(`+`)) %>% 
   transmute(date, group, !!! parse_exprs(expr), col5) %>%
   rename_at(3:6, ~ nm1)
# A tibble: 8 x 7
#   date group  col1  col2  col3  col4  col5
#  <int> <int> <int> <int> <int> <int> <int>
#1  1234     1     3     1     0     2    94
#2  1235     1     0     3     2     0   195
#3  1234     1     0     0     5     0   402
#4  1235     1     4     0     0     6   903
#5  1235     2     0     0     0    94   761
#6  1233     2     0     0    53     0   861
#7  1342     2    18     0    44     0   -37
#8  1234     2    66    13    45     1    46

或转换为“long”格式进行计算,然后将其更改为“wide”。

代码语言:javascript
复制
library(tidyverse)
df1 %>% 
  rownames_to_column('rn') %>%
  gather(key, val, col1:col4) %>%
  group_by(group, key, sn= sign(val)) %>% 
  mutate(mnVal = min(val)) %>%
  group_by(rn) %>% 
  mutate(col5 = col5 + sum(mnVal), val = val - mnVal) %>% 
  select(-sn, -mnVal) %>%
  spread(key, val) %>%
  ungroup %>% 
  select(names(df1))

数据

代码语言:javascript
复制
df1 <- structure(list(date = c(1234L, 1235L, 1234L, 1235L, 1235L, 1233L, 
1342L, 1234L), group = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), col1 = c(-2L, 
4L, -5L, 8L, -72L, 32L, -54L, 98L), col2 = c(3L, 5L, 2L, 2L, 
83L, -21L, 0L, -8L), col3 = c(4L, -2L, 9L, -4L, -54L, -1L, -10L, 
-9L), col4 = c(-5L, -7L, 1L, 7L, 98L, 4L, -11L, -10L), col5 = c(100L, 
200L, 400L, 900L, 800L, 900L, 100L, 100L)), .Names = c("date", 
"group", "col1", "col2", "col3", "col4", "col5"), 
  class = "data.frame", row.names = c(NA, 
-8L))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50801042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档