如果> 0计数到R中的频率分布

时间:2018-03-06 03:19:46

标签: r dplyr

假设我手头有900个数据帧,我希望得到类似于基于每个“类型”的另一列的频率分布。

示例代码makin;

df1 <- as_tibble(iris)
df2 <- slice(df1, 1:7) 
df2 <- df2 %>% 
  mutate(type = 1:7)

这类似于我目前只使用一个数据帧:

df2 %>% select(type, Sepal.Length) %>%
  mutate(Count = ifelse(Sepal.Length > 0, 1, 0)) %>%
  mutate(Percentage = Count/7)

对于任何行,Sepal.Length = 0,那么我不会计算它(对于该行值,count列将为= 0)。

但是我将有900个数据帧,我将运行此代码,所以我正在考虑通过循环运行它。

理想情况下,如果输入两个数据帧,并且第一行的Sepal.Length值> 0,那么我希望第1行/类型1的计数为2.有没有更好的方法来解决这个问题?如果我确实选择了循环选项,那么有没有办法将所有数据帧组合起来告诉R第1行/第1行有多个&gt; 0值?

3 个答案:

答案 0 :(得分:0)

对于您的虹膜示例,您想要的是:

library(tidyverse)
df1 <- as_tibble(iris)
df2 <- slice(df1, 1:7) 
df2 <- df2 %>% 
  mutate(type = 1:7)

group_by(df2, type) %>%
  transmute(has_sepal = sum(Sepal.Length > 0))
#   A tibble: 7 x 2
#   Groups:   type [7]
#    type has_sepal
#   <int>     <int>
# 1     1         1
# 2     2         1
# 3     3         1
# 4     4         1
# 5     5         1
# 6     6         1
# 7     7         1

要做到这一点超过900个数据帧...如果你想要这个在虹膜,硬编码上工作。熟悉使用tidyverse评估编写函数的人可以为你编写更通用的版本,但这仍然在我的待办事项列表中。

f_fill_in_blank_first <- function(tib){
# hard code the var1 and var2
    group_by(tib, <var1>) %>%
      transmute(var1_not_zero = sum(<var 1> != 0))
}

f_iris <- function(tib)
    group_by(tib, type) %>%
        transmute(var1_not_zero = sum(Sepal.Length != 0)
}

根据你的900个数据帧的结构,你可以使用这个函数进行vapply(编辑,不,不是这个函数,重构因此,如果你想要使用这个函数,它会生成一个命名的原子向量)将整个事物放入一个数组,然后使用apply和sum折叠其中一个维度

答案 1 :(得分:0)

如果你想保留你的代码:

df2 %>% select(type, Sepal.Length) %>%
mutate(Count = ifelse(Sepal.Length > 0, 1, 0)) %>%
mutate(Percentage = Count/7) 

您可以将其包装到函数(add_a_count)中:

library(tidyverse)
df1 <- as_tibble(iris)
df2 <- df1 %>% 
    mutate(type = nrow(df1))

add_a_count = function(df)
{
counted_df = df %>% 
           select(type, Sepal.Length) %>%
           mutate(Count = ifelse(Sepal.Length > 0, 1, 0),
           Percentage = Count/7)
return(counted_df)
}   

我使用以下函数生成100个重复的测试df2

duplicate_df = function(df, no_duplicates)
{
tmp_df_list = list()
for(i in c(1:no_duplicates))
    {
    print(paste0("Duplicate ", i, " generated."))
    tmp_df_list[[i]] = df
    }
return(tmp_df_list)
}

data_frames_list = duplicate_df(df = df2, no_duplicates = 100)

并将其与lapplycounted_data_frames = lapply(data_frames_list, add_a_count)

一起使用

列表counted_data_frames可以相对容易地被操作(如果你想要一个非列表输出,你可以使用另一个apply函数)。这可能不是最快的方法,但它很简单。

修改

您可以通过循环遍历数据框列表来获取Counts列。新数据框counts_data_frame包含所有计数,每列都是一个原始数据框的计数:

counts_data_frame = data.frame(type = seq(from = 1, to = nrow(df2)))

for(i in c(1:length(counted_data_frames)))
{
  counts_data_frame = cbind(counts_data_frame, as.vector(counted_data_frames[[i]]["Count"]))
}

当循环遍历这个新数据框的行时,您可以总结您的计数并获得绘图计数的向量:

counts_summarised = vector(length = nrow(counts_data_frame))

for(i in c(1:nrow(counts_data_frame)))
{
  counts_summarised[i] = sum(counts_data_frame[i, 2:ncol(counts_data_frame)])
}

plot(counts_summarised, ylab = "Counts", xlab = "Type")

答案 2 :(得分:0)

在此解决方案中,我将向您展示如何:

  1. 将所有CSV文件导入列表中的单独数据框,假设它们对您感兴趣的变量都具有相同的列名,并且文件位于一个文件夹中(最好是您的工作目录);
  2. 计算0和非零测量的数量及其比例;
  3. 将列表转换为数据框
  4. 具体来说,我使用lapply()来循环data.frame,使用data.frame将列表转换为enframe(),并使用unnest()取消值列,并pct使用type传播spread()

    让我们先创建一个可以使用的数据。

    library(tidyverse)
    
    # create a list
    datlist <- list()
    # this list will contain ten data frames with 
    # a sample with up to 8 0's and 20 random uniforms as observations 
    for (i in seq_len(10)){
      datlist[[i]] = data.frame(x = sample(c(sample(c(0,1,2,3,4), 8, replace = T), runif(20,0,10))))
    }
    # name each element of the list datlist
    name_element <- LETTERS[1:10]
    datlist <- set_names(datlist, name_element)
    # save each file separately
    mapply(write.csv, datlist, file=paste0(names(datlist), '.csv'), row.names = FALSE)
    

    以下将import your data into R and store them as data.frames in a list

    # import all csv files in the folder into separate data frames in the temp list
    temp <- list.files(pattern = "*.csv")
    myfiles <- lapply(temp, read.csv)
    

    如果我们假设每个文件包含相同的变量,则以下将按类型计算百分比。

    # Calculate the frequency and relative distributions 
    lapply(myfiles, 
           function(varname) mutate(varname, type = if_else(x == 0, 0, 1)) %>%
             group_by(type) %>% summarise(n = n()) %>% 
             mutate(pct = n / sum(n))
           ) %>% 
      enframe() %>% # convert the list into a data.frame
      unnest(value) %>% # unnest the values
      spread(type, pct) # spread the values by type
    
    
    # A tibble: 17 x 4
        name     n     `0`    `1`
       <int> <int>   <dbl>  <dbl>
     1     1     3  0.107  NA    
     2     1    25 NA       0.893
     3     2    28 NA       1.00 
     4     3     1  0.0357 NA    
     5     3    27 NA       0.964
     6     4     2  0.0714 NA    
     7     4    26 NA       0.929
     8     5    28 NA       1.00 
     9     6    28 NA       1.00 
    10     7     2  0.0714 NA    
    11     7    26 NA       0.929
    12     8     3  0.107  NA    
    13     8    25 NA       0.893
    14     9     1  0.0357 NA    
    15     9    27 NA       0.964
    16    10     1  0.0357 NA    
    17    10    27 NA       0.964