在R中计算if> 0到频率分布

问题描述 投票:2回答:3

假设我手头有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行有多个> 0值?

r dplyr
3个回答
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折叠其中一个维度


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")

0
投票

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

  1. 将所有CSV文件导入列表中的单独数据框,假设它们对您感兴趣的变量都具有相同的列名,并且文件位于一个文件夹中(最好是您的工作目录);
  2. 计算0和非零测量的数量及其比例;
  3. 将列表转换为数据帧

具体来说,我使用lapply()循环通过data.frames,使用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
© www.soinside.com 2019 - 2024. All rights reserved.