如何基于(按元素)选定的相邻列计算重复项的按行计数

时间:2018-12-20 11:03:19

标签: r count duplicates elementwise-operations rowwise

我有一个数据框测试

group userID A_conf A_chall B_conf B_chall
1    220      1       1      1       2     
1    222      4       6      4       4     
2    223      6       5      3       2     
1    224      1       5      4       4    
2    228      4       4      4       4    

数据包含每个用户的响应(由用户ID显示),其中每个用户都可以为这两个度量输入介于1到6之间的任何值:

  • conf
  • 挑战

他们还可以选择不回复,从而产生 NA 条目。

测试数据框包含A,B,C,D等几列。可以分别为每个列报告Conf和Chall度量。

我有兴趣进行以下比较:

  • A_conf A_chall
  • B_conf B_chall

如果这些度量中的任何一个相等,则应增加 Final 计数器(如下所示)。

group userID A_conf A_chall B_conf B_chall Final
1    220      1       1      1       2     1
1    222      4       6      4       4     1
2    223      6       5      3       2     0
1    224      1       5      4       4     1
2    228      4       4      4       4     2

我正在与最终柜台挣扎。什么脚本可以帮助我实现此功能?

作为参考,测试数据框集的计算结果在以下共享:

  • dput(测试):

    结构(列表(group = c(1L,1L,2L,1L,2L),

    userID = c(220L,222L,223L,224L,228L),

    A_conf = c(1L,4L,6L,1L,4L),

    A_chall = c(1L,6L,5L,5L,4L),

    B_conf = c(1L,4L,3L,4L,4L),

    B_chall = c(2L,4L,2L,4L,4L)),

    class =“ data.frame”,row.names = c(NA,-5L))

我尝试了这样的代码:

test$Final = as.integer(0)   # add a column to keep counts
count_inc = as.integer(0)    # counter variable to increment in steps of 1

for (i in 1:nrow(test)) {

    count_inc = 0

    if(!is.na(test$A_conf[i] == test$A_chall[i]))
    {
      count_inc = 1
      test$Final[i] = count_inc
    }#if

    else if(!is.na(test$A_conf[i] != test$A_chall[i]))
    {
      count_inc = 0
      test$Final[i] = count_inc
    }#else if
}#for

上面的代码仅在 A_conf A_chall 列上有效。问题是,无论(用户)输入的值是否相等,最终列均用全1填充。

3 个答案:

答案 0 :(得分:4)

一个基本的R解决方案,假设您拥有相同数量的“ conf”和“ chall”列

@Service
class YourService {
   @Autowired
   @Lazy
   YourService  self;         

   callAsyncFunction(){
      self.function(); //@Async will work here 
   }

   @Async("poolbeanname") 
   function () {
      CompletableFuture.completedFuture( futureResult);
   } 
}

也可以单线完成

#Find indexes of "conf" column
conf_col <- grep("conf", names(test))

#Find indexes of "chall" column
chall_col <- grep("chall", names(test))

#compare element wise and take row wise sum
test$Final <- rowSums(test[conf_col] == test[chall_col])


test
#  group userID A_conf A_chall B_conf B_chall Final
#1     1    220      1       1      1       2     1
#2     1    222      4       6      4       4     1
#3     2    223      6       5      3       2     0
#4     1    224      1       5      4       4     1
#5     2    228      4       4      4       4     2

答案 1 :(得分:2)

使用tidyverse,您可以执行以下操作:

df %>%
 select(-Final) %>%
 rowid_to_column() %>% #Creating an unique row ID
 gather(var, val, -c(group, userID, rowid)) %>% #Reshaping the data
 arrange(rowid, var) %>% #Arranging by row ID and by variables
 group_by(rowid) %>% #Grouping by row ID
 mutate(temp = gl(n()/2, 2)) %>% #Creating a grouping variable for different "_chall" and "_conf" variables
 group_by(rowid, temp) %>% #Grouping by row ID and the new grouping variables
 mutate(res = ifelse(val == lag(val), 1, 0)) %>% #Comparing whether the different "_chall" and "_conf" have the same value
 group_by(rowid) %>% #Grouping by row ID
 mutate(res = sum(res, na.rm = TRUE)) %>% #Summing the occurrences of "_chall" and "_conf" being the same
 select(-temp) %>% 
 spread(var, val) %>% #Returning the data to its original form
 ungroup() %>%
 select(-rowid)

  group userID   res A_chall A_conf B_chall B_conf
  <int>  <int> <dbl>   <int>  <int>   <int>  <int>
1     1    220    1.       1      1       2      1
2     1    222    1.       6      4       4      4
3     2    223    0.       5      6       2      3
4     1    224    1.       5      1       4      4
5     2    228    2.       4      4       4      4

答案 2 :(得分:2)

您也可以尝试此tidyverse。与其他答案相比,行数更少;)

library(tidyverse)
d %>% 
  as.tibble() %>% 
  gather(k, v, -group,-userID) %>% 
  separate(k, into = c("letters", "test")) %>% 
  spread(test, v) %>% 
  group_by(userID) %>% 
  mutate(final = sum(chall == conf)) %>% 
  distinct(userID, final) %>% 
  ungroup() %>% 
  right_join(d)
# A tibble: 5 x 7
  userID final group A_conf A_chall B_conf B_chall
   <int> <int> <int>  <int>   <int>  <int>   <int>
1    220     1     1      1       1      1       2
2    222     1     1      4       6      4       4
3    223     0     2      6       5      3       2
4    224     1     1      1       5      4       4
5    228     2     2      4       4      4       4