Сохранение выходных данных str_which l oop в R - PullRequest
3 голосов
/ 14 февраля 2020

Я работаю с листом данных, в котором перечислены различные научные c публикации. Строки - это публикации, столбцы - это различные метрики, описывающие каждую публикацию (имя и должность автора, идентификаторы изданий, дата и т. Д. c ...). Я хочу отфильтровать публикации для каждого автора и извлечь их части. Предостережение - это формат: все имена авторов (5-80 на ячейку) объединяются в одну ячейку для каждой строки.

Мне удалось решить эту проблему с помощью str_which, сохранив координаты для каждого автор, а затем выдержка. Это работает только для ручного использования. Когда я пытаюсь автоматизировать этот процесс, используя al oop для рисования списка авторов, я не могу сохранить вывод.

Я немного растерялся из-за того, как сохранить результаты, не перезаписывая предыдущие.

sampleDat <- 
  data.frame(var1 = c("Doe J, Maxwell M, Kim HE", "Cronauer R, Carst W, Theobald U", "Theobald U, Hey B, Joff S"),
             var2 = c(1:3),
             var3 = c("2016-01", "2016-03", "2017-05"))

список имен, для которых мне нужны координаты

namesOfInterest <-
  list(c("Doe J", "Theobald U"))

ручное извлечение, требующее от меня ввода точного имени и вывода объекта

Doe <- str_which(sampleDat$var1, "Doe J")           
Theobald <- str_which(sampleDat$var1, "Theobald U") 

одна из многих попыток, которая не повторяет ручную версию.

results <- c()

for (i in namesOfInterest) {
  results[i] <- str_which(sampleDat$var1, i)
}

Ответы [ 2 ]

2 голосов
/ 14 февраля 2020

Неправильно настроено значение для l oop (должно быть что-то вроде for(i in 1:n){do something}). Кроме того, даже если вы исправите это, вы получите ошибку, связанную с тем фактом, что str_which возвращает вектор переменной длины , указывающий положение каждого из найденных совпадений (и это может привести к несколько матчей). Таким образом, индексирование вектора в al oop здесь не сработает, потому что, когда у автора несколько совпадений, более чем одна запись будет сохранена в одном элементе, что приведет к ошибке.

Решите это, работая со списками, потому что списки могут содержать векторы произвольной длины. Индексируйте список с помощью двойных скобок: [[.

library(stringr)
sampleDat <- 
  data.frame(var1 = c("Doe J, Maxwell M, Kim HE", "Cronauer R, Carst W, Theobald U", "Theobald U, Hey B, Joff S"),
             var2 = c(1:3),
             var3 = c("2016-01", "2016-03", "2017-05"))

# no need for list here. a simple vector will do
namesOfInterest <- c("Doe J", "Theobald U")

# initalize list
results <- vector("list", length = length(namesOfInterest))

# loop over list, saving output of `str_which` in each list element.
# seq_along(x) is similar to 1:length(x)
for (i in seq_along(namesOfInterest)) {
  results[[i]] <- str_which(sampleDat$var1, namesOfInterest[i])
}

, что возвращает:

> results
[[1]]
[1] 1

[[2]]
[1] 2 3

Чтобы понять вышеприведенный вывод, является элемент ith списка , results[[i]] содержит вывод str_which(sampleDat$var1, namesOfInterest[i]), где namesOfInterest[i] всегда точно один автор. Однако длина results[[i]] может быть больше единицы:

> sapply(results, length)
[1] 1 2

, что означает, что один автор может быть упомянут несколько раз. В приведенном выше примере sapply считает длину каждого вектора в списке results, показывая, что namesOfInterest[1] имеет одну бумагу, а namesOfInterest[2] имеет 2. `

1 голос
/ 15 февраля 2020

Вот еще один подход для вас. Если вы хотите узнать, какой ученый находится в какой публикации, вы также можете сделать следующее. Сначала назначьте уникальные идентификаторы публикациям. Затем разделите авторов и создайте фрейм данных в длинном формате. Определите группы по авторам и объедините идентификатор публикации (pub_id) в виде строки (символа). Если вам нужно извлечь некоторых авторов, вы можете использовать этот фрейм данных (foo) и строки подмножества.

library(tidyverse)

mutate(sampleDat, pub_id = 1:n()) %>% 
separate_rows(var1, sep = ",\\s") %>% 
group_by(var1) %>% 
summarize(pub_id = toString(pub_id)) -> foo

  var1       pub_id
  <chr>      <chr> 
1 Carst W    2     
2 Cronauer R 2     
3 Doe J      1     
4 Hey B      3     
5 Joff S     3     
6 Kim HE     1     
7 Maxwell M  1     
8 Theobald U 2, 3 


filter(foo, var1 %in% c("Doe J", "Theobald U"))

  var1       pub_id
  <chr>      <chr> 
1 Doe J      1     
2 Theobald U 2, 3  

Если вы хотите, чтобы индекс был равен цифре c, вы можете исказить идею выше и сделать последующий. Вы можете подмножество строк с целевыми именами с filter().

mutate(sampleDat, pub_id = 1:n()) %>% 
separate_rows(var1, sep = ",\\s") %>% 
group_by(var1) %>% 
summarize(pub_id = list(pub_id)) %>% 
unnest(pub_id) 

  var1       pub_id
  <chr>       <int>
1 Carst W         2
2 Cronauer R      2
3 Doe J           1
4 Hey B           3
5 Joff S          3
6 Kim HE          1
7 Maxwell M       1
8 Theobald U      2
9 Theobald U      3
...