子集对应于数据框中另一列的两列的所有值

Subset all values from two columns that correspond to another column(s) in a dataframe

我有一个包含 4 列的数据框

ID1 ID2 Value1 Value2
1 2 zinc sulfur
1 2 zinc calcium
1 2 calcium NA
3 4 carbon iron
3 4 iron iron
3 4 iron carbon

前两列始终对应,因此在配置时我基本上只需要使用其中一个 ID 列。

对于每对 ID,我希望每个值都对应于其中一个 ID,并且只出现一次。

所以对于上面的例子我想要:

ID1 ID2 Values
1 2 zinc, sulfur, calcium
3 4 carbon, iron

但是,如果列表仅列出每个 ID 的每个值(唯一出现)的次数,它也可能有效。

我最终想要的是每个Value在数据集中出现的次数

例如:

Value Count
calcium 1
carbon 1
zinc 1
iron 1
sulfur 1

我想列表可能是到达此端点的更好方法,但我更精通数据框。目前,我最感兴趣的是第一部分(获取 ID 对的每个值)。

这是解决您第一个问题的dplyr方法。

首先 group_by 你的 ID 列,然后使用 summarisepaste 并将它们折叠成单行 comma-separated 字符串每个 ID 对(并通过 na.omit 删除 NA)。

最后,str_split 逗号分隔字符串删除重复元素,paste 将它们重新组合在一起,ungroup.

library(dplyr)

df %>% 
  group_by(ID1, ID2) %>% 
  summarize(Values = paste0(na.omit(Value1), ",", na.omit(Value2), collapse = ",")) %>% 
  mutate(Values = paste0(unique(sort(str_split(Values, ",", simplify = T))), collapse = ",")) %>% 
  ungroup()

# A tibble: 2 × 3
    ID1   ID2 Values             
  <int> <int> <chr>              
1     1     2 calcium,sulfur,zinc
2     3     4 carbon,iron  

数据

df <- read.table(header = T, text = "
ID1 ID2 Value1  Value2
1   2   zinc    sulfur
1   2   zinc    calcium
1   2   calcium NA
3   4   carbon  iron
3   4   iron    iron
3   4   iron    carbon")

tidyverse 中,该过程是在 tidy 数据集中收集 value1 和 value2,group_by 您的 id 变量,以及 summarize 使用字符串的串联值。

library(tidyverse)

id1 <- c(1,1,1,3,3,3)
id2 <- c(2,2,2,4,4,4)
Value1 <- c("zinc", "zinc", "calcium", "carbon", "iron", "iron")
Value2 <- c("sulfer", "calcium", NA, "iron", "iron", "carbon")

df <- as_tibble(cbind(id1,id2,Value1,Value2))

df_cln <- df %>%
  gather(var, value, -id1, -id2, na.rm = T) %>%
  select(-var) %>%
  unique() %>%
  group_by(id1, id2) %>%
  summarise(minerals=paste0(value, collapse=","))

print(df_cln)

# A tibble: 2 × 3
# Groups:   id1 [2]
  id1   id2   minerals           
  <chr> <chr> <chr>              
1 1     2     zinc,calcium,sulfer
2 3     4     carbon,iron    

这个呢?

data.frame(table(unlist(df[, sapply(df, is.character)])))

     Var1 Freq
1 calcium    2
2  carbon    2
3    iron    4
4  sulfer    1
5    zinc    2

数据

df <- structure(list(ID1 = c(1, 1, 1, 3, 3, 3), ID2 = c(2, 2, 2, 4, 
4, 4), Value1 = c("zinc", "zinc", "calcium", "carbon", "iron", 
"iron"), Value2 = c("sulfer", "calcium", NA, "iron", "iron", 
"carbon")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-6L))

# A tibble: 6 x 4
    ID1   ID2 Value1  Value2 
  <dbl> <dbl> <chr>   <chr>  
1     1     2 zinc    sulfer 
2     1     2 zinc    calcium
3     1     2 calcium NA     
4     3     4 carbon  iron   
5     3     4 iron    iron   
6     3     4 iron    carbon

使用 dplyr 的一个选项也是 t 排列 'Value' 列,在 toString 之后得到 uniquepaste分组

library(dplyr)
df %>% 
 group_by(ID1, ID2) %>% 
 summarise(Values = toString(na.omit(unique(c(t(across(starts_with("Value"))))))), 
       
    .groups = 'drop')

-输出

# A tibble: 2 × 3
    ID1   ID2 Values               
  <int> <int> <chr>                
1     1     2 zinc, sulfur, calcium
2     3     4 carbon, iron