根据名称循环遍历数据框。

4

我希望你能够帮忙翻译一个简单的R语言问题。我有一系列数据框,它们具有重复的名称结构。我想循环遍历它们并进行一些分析。以下是使用一些虚假数据硬编码示例:

#Create some fake data
n1 = c(2, 3, 5, 7) 
s1 = c(1, 1, 2, 0) 
b1 = c(6, 0, 0, 0) 
Tank001.df = data.frame(n1, s1, b1)

n2 = c(1, 2, 4, 6) 
s2 = c(2, 2, 0, 0) 
b2 = c(8, 9, 10, 0) 
Tank002.df = data.frame(n2, s2, b2)

n3 = c(7, 12, 0, 0) 
s3 = c(5, 3, 0, 0) 
b3 = c(8, 9, 10, 4) 
Tank003.df = data.frame(n3, s3, b3)

我希望自动化的第一个操作是将0值转换为“NA”。这是硬编码版本,但我最好根据我拥有的Tankxxx.df数据框的数量自动化此过程:
#Convert zeros to NA
Tank001.df[Tank001.df==0] <- NA
Tank002.df[Tank002.df==0] <- NA
Tank003.df[Tank003.df==0] <- NA

最后,我想完成一系列数据查询,其中一个简单的例子可能是每个数据框中小于5的值的数量:

#Return the number of values smaller than 5
Tank001.less.than.5 <- numeric(length(Tank001.df))
for (i in 1:(length(Tank001.df))) {Tank001.less.than.5[i] <- sum(Tank001.df[[i]] < 5,na.rm=TRUE)} 
Tank002.less.than.5 <- numeric(length(Tank002.df))
for (i in 1:(length(Tank002.df))) {Tank002.less.than.5[i] <- sum(Tank002.df[[i]] < 5,na.rm=TRUE)} 
Tank003.less.than.5 <- numeric(length(Tank003.df))
for (i in 1:(length(Tank003.df))) {Tank003.less.than.5[i] <- sum(Tank003.df[[i]] < 5,na.rm=TRUE)} 

理想情况下,我还想知道如何将这些简单计算的结果写入新的数据框中。例如,在本例中,是Less.than.5$TankXXX等。

任何帮助都将不胜感激。


对于具有源数据和期望输出的可重现示例,加1分。 - A5C1D2H2I1M1N2O1R2T1
2个回答

4
创建一个你的数据框的列表,并使用以下组合的lapply和sapply:
TankList <- list(Tank001.df, Tank002.df, Tank003.df)
lapply(TankList, function(x) {
  x[x == 0] <- NA
  sapply(x, function(y) sum(y < 5, na.rm = TRUE))
})
# [[1]]
# n1 s1 b1 
#  2  3  0 
# 
# [[2]]
# n2 s2 b2 
#  3  2  0 
# 
# [[3]]
# n3 s3 b3 
#  0  1  1 

感谢您提供迅速的解决方案。由于我以前没有使用过列表,因此如何获取n1、s1和b1的平均值的语法是什么?例如,上面示例的期望结果将为1.67、1.67、0.67。 - user1912925
@user1912925,抱歉,我不明白你是如何得出那些结果的。你能解释一下吗?我会尽力帮助你的。 - A5C1D2H2I1M1N2O1R2T1
@AnandaMahto 我认为他想要所有 n* 的平均值等等(但他的值是不正确的)。可以使用 sapply 跨越每个列表的第 k 个元素,或将结果转换为矩阵并计算 colMeans - Carl Witthoft

3
这也适用于单个lapplycolSums的情况:
l <- list(Tank001.df, Tank002.df, Tank003.df) # create a list

lapply(l, function(x) colSums("is.na<-"(x, !x) < 5, na.rm = TRUE))

# [[1]]
# n1 s1 b1 
#  2  3  0 
# 
# [[2]]
# n2 s2 b2 
#  3  2  0 
# 
# [[3]]
# n3 s3 b3 
#  0  1  1 

+1,但肯定不是最令人难忘或最常见的语法! - A5C1D2H2I1M1N2O1R2T1
1
+1!我可以建议使用类似 l <- mget(ls(pattern='Tank.*df$') 的方法,以避免手动创建列表... - agstudy
@agstudy 好主意!mget函数需要一个环境参数:mget(ls(pattern='Tank.*df$'), globalenv()) - Sven Hohenstein
@SvenHohenstein 是的,但在这种情况下不需要。它与 ls 相同的参数(环境)。 - agstudy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接