У меня есть фрейм данных с 4 столбцами
ID1 | ID2 | Значение1 | Значение2 |
---|---|---|---|
1 | 2 | цинк | сера |
1 | 2 | цинк | кальций |
1 | 2 | кальций | нет данных |
3 | 4 | углерод | железо |
3 | 4 | железо | железо |
3 | 4 | железо | углерод |
Первые два столбца всегда будут соответствовать друг другу, поэтому мне нужно работать только с одним из столбцов ID при настройке.
Для каждой пары идентификаторов я хочу, чтобы каждое значение, соответствующее любому из идентификаторов, появлялось только один раз.
Итак, для приведенного выше примера я хочу:
ID1 | ID2 | Ценности |
---|---|---|
1 | 2 | цинк, сера, кальций |
3 | 4 | углерод, железо |
Но список также может работать, если он просто перечисляет количество раз, которое каждое значение (уникально появляется) для каждого идентификатора.
В конечном итоге я хочу, чтобы каждое значение появлялось в наборе данных.
например:
Ценность | Считать |
---|---|
кальций | 1 |
углерод | 1 |
цинк | 1 |
железо | 1 |
сера | 1 |
Я предполагаю, что список может быть лучшим способом добраться до этой конечной точки, но я лучше разбираюсь в работе с фреймами данных. На данный момент меня в основном интересует первая часть (получение каждого значения для пары идентификаторов).
Я сделал это быстро и по ошибке соединил кальций и углерод. Отредактировал сейчас.
Вот dplyr
подход к решению вашей первой проблемы.
Сначала group_by
ваши ID
столбцы, затем используйте summarise
для paste
и сворачивайте их в одну строку строки, разделенной запятыми, на ID
пару (а также удаляет NA
на na.omit
).
Наконец, 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
процесс состоит в том, чтобы собрать значение1 и значение2 в tidy
наборе данных, 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
переставить столбцы «Значение», получить unique
и paste
с помощью toString
после группировки.
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
Немного другой вариант (на одну функцию меньше), с unlist
: toString(na.omit(unique(unlist(across(Value1:Value2)))))
@Maël Сначала я думал об этом, но он возвращает порядок по-другому, поскольку кажется, что OP не ожидал, что порядок строк будет сохранен.
Это верно! не видел этого
Почему кальций имеет значение 2 в предполагаемом выводе, если только
ID
== 1 имеет значение кальция?