在循环数据帧时向向量添加计数

时间:2017-05-04 22:30:35

标签: arrays r string for-loop count

我在R.相对较新。我正在开展一个项目,其中有一列ID(PMID),一列MESH术语,基本上是很多生物医学总结术语(MH),以及按顺序组织的年份列(EDAT_Year)。我的目标是创建一个向量,该向量包含每年MESH术语中特定单词的计数。基本上,如果一行包含单词(不是它在行中的次数,而是它的存在),它应该被计算并在向量中用年份分隔。

这是一个例子。假设这是数据帧:

  PMID    MH                            EDAT_Year
  1       Male, Lung, Heart, Aneurysm   1978
  2       Male, Male, Anemia, Lung      1978
  3       Heart, Anemia, Adult          1980
  4       Female, Heart, Blood, Acute   1980
  5       Male, Blood, Adult, Lung      1980
  6       Male, Kidney, Brain, Heart    1983
  7       Male, Lung, Blood, Male       1983

然后,如果我要测试"男性",我希望输出

  2 1 2

表示在1978年有2个观察结果包含"男性",1980年1个,1983年2个(无论它出现了多少次)。

我目前正在工作3年,但希望扩展到更多。我能够用以下3年手动完成这项工作(顺便提到1978年,1980年,1983年),其中我创建了多个列,如果它们属于那一年,则只包含MESH术语:

# count occurrences in the three years
disease_78 <- length(grep("\\Male\\>", total$MH_78))
disease_80 <- length(grep("\\Male\\>", total$MH_80))
disease_83 <- length(grep("\\Male\\>", total$MH_83))

但是现在我正在尝试编写一个函数,这样如果我输入一个短语,我会在一个向量中得到所有出现的内容,而不是每年手动复制和粘贴或有数百个列。这就是我到目前为止所做的:

# function of count occurences
count_fxn <- function(x)
{
  # read in argument as character
  phrase_to_count <- deparse(substitute(x))

  # create a vector to store count values
  count_occur <- numeric(0)

  # a vector for how many years there are
  num_years <- seq(1, 3, 1)

  # loop through entire data frame
  for (i in 1:length(total$PMID))
  {
    # loop through the three years
    for(j in 1:length(num_years))
    {
      # if at least one occurence occurs in row cell, increment count
      if (length(grep(phrase_to_count, total$MH[i]) > 0))
      {
        count_occur[j] <- count_occur[j] + 1
      }
      # if the next row's year is different than the current one's, move to 
      # next spot for next year in vector
      if (total$EDAT_Year[i] != total$EDAT_Year[i+1])
      {
        j <- j + 1
      }
      # increment so go to next line to read in data
      i <- i + 1
    }
  }
  return(count_occur) 
}
# using function
count_fxn(Male)

但这是我不断得到的错误:

 Error in if (total$EDAT_Year[i] != total$EDAT_Year[i + 1]) { : 
 missing value where TRUE/FALSE needed

当我改变

if (total$EDAT_Year[i] != total$EDAT_Year[i + 1])

if (total$EDAT_Year[j] != total$EDAT_Year[j + 1])

我没有收到任何错误,相反,输出是

NA NA NA

什么时候应该是

3453 2343 5235

表示包含的观察数量&#34;男性&#34;其中,分别是1978年,1980年和1983年。

请指教。我还不是最强的编码器,而且我确定它可以在更短的时间内完成,我已经在这个工作了2个小时。

2 个答案:

答案 0 :(得分:2)

您可以使用by()

with(df, lengths(by(MH, EDAT_Year, grep, pattern="Male")))
# EDAT_Year
# 1978 1980 1983 
#    2    1    2 

答案 1 :(得分:0)

如果你想计算每个&#34;字的出现次数&#34;在MH每年,无需输入每个单词或创建单词列表,您可以按如下方式进行:

DF <- read.table(text="PMID    MH   EDAT_Year
1       Male,Lung,Heart,Aneurysm   1978
2       Male,Male,Anemia,Lung      1978
3       Heart,Anemia,Adult          1980
4       Female,Heart,Blood,Acute   1980
5       Male,Blood,Adult,Lung      1980
6       Male,Kidney,Brain,Heart    1983
7       Male,Lung,Blood,Male       1983", header=T)

DF <- DF %>% 
  #Convert MH column to nested list
  dplyr::mutate(MH = strsplit(as.character(MH), ",")) %>% 
  #reashape data into tidy format
  tidyr::unnest(MH) %>% 
  #eliminate duplicates to not count PMIDs with multiple identical entries in MH
  unique() %>% 
  #count entries for each value in MH by year
  reshape2::dcast(EDAT_Year ~ MH) 

DF

结果:

  EDAT_Year Acute Adult Anemia Aneurysm Blood Brain Female Heart Kidney Lung Male
1      1978     0     0      1        1     0     0      0     1      0    2    2
2      1980     1     2      1        0     2     0      1     2      0    1    1
3      1983     0     0      0        0     1     1      0     1      1    1    2