使用 R 计算数据集中每个组的正态性
Posted
技术标签:
【中文标题】使用 R 计算数据集中每个组的正态性【英文标题】:Calculate normality of each group in a dataset using R 【发布时间】:2016-09-14 09:20:00 【问题描述】:我有一个包含大约 7 个条目的数据集。假设它有 5 列:
Cust_Id(around 340 unique Ids), Expense_Type, Expense($), Income_Type and Income($).
我想检查通过统计分析确定的任何Cust_Id
组内的收入和费用的相对稳定性。
我使用R的summaryBy
函数找出了数据的统计信息(均值、中位数、标准差)。
现在我想找到每组Cust_Id
的正态性。我使用了shapiro.test()
函数,但它会导致整个数据的正态性得分,而不是分组值的正态性得分。我是否在解决需求的正确道路上?我是这个领域的新手。请提出解决此问题的方法。
样本数据:
Cust_Id Income_Type Income Expense_Type Expense
10001 ABC 4356.89 XYZ 569.45
10003 DEF 5678.34 PQR 4532.43
10006 FRG 5783.43 JHK 9724.56
10001 DEG 5345.34 HTY 7856.34
10008 HGT 678.67 KIL 7893.13
10003 GRT 678.67 JHK 6544.11
【问题讨论】:
您正在寻找的测试是否有特定的价值? 你试过我的吗?最后一个使用 split 非常简单。调用您的示例数据 data 并将 Expenses($) 更改为 Income 以获取每个 id 组的收入正常性,就像您尝试使用 Cedric 的答案一样。 对不起,我以为你的数据框被命名为 Cust_id,我已经更改了我的脚本。 @Pierre 我想找到每个客户 ID 组的收入和费用的正态性分数。 嘿,我从这两种方法中得到了结果。对您的代码进行细微调整,最终完成。谢谢大家!! 【参考方案1】:尝试对数据进行子集化,您可以使用循环并将结果存储在列表中。
listids <- list()
for (ids in unique(df$Cust_Ids))
subdf <- subset(x=df, subset=Cust_Ids==ids)
# apply the rest of your analysis there using subdf, for instance
listids[[ids]] <- shapiro.test(subdf$Expense)
【讨论】:
就像奥利说的你也可以使用apply,这样会更快 在帮助新用户时,重要的是获得与数据框名称完全相同的简单信息。您知道要更改名称以匹配,但事实并非如此。您已将对象命名为Cust_Id
,列名为 Ids
,并且他们有一个名为 df
的对象,列名为 Cust_Id
。
我知道 OP 没有在问题中提供数据框名称,但即便如此,调用对象 Cust_Id
肯定会导致错误。
你说得对,我没看错。我会做相应的改变。
@Cedric 此代码再次返回一个空数据框 subdf。【参考方案2】:
不确定我是否理解这个问题。示例数据会有所帮助。如果您正在寻找测试每列的正态性,您可以只对每个相关列运行测试。
例如,如果您的数据集名为 data
并且是一个 data.table,请参阅 class(data)
:
Expense <- data$Expense
shapiro.test(Expense)
您可以遍历列(请参阅apply
函数系列),或者如果您只有几个列,则在相关的地方重复上述内容。
根据您要弄清楚的内容,有多个测试: https://en.wikipedia.org/wiki/Normality_test#Frequentist_tests
如果您有一百万个Cust_Id
,其中有 340 个唯一身份,您可以为每个唯一群组创建子表并测试每个群组的正态性。如果这是您想要的,我可以编写一个循环,然后为您提供 340 个唯一 ID 中每一个的特定列的正态性?
类似:
library(data.table)
data <- data.table(data)
对于一个 ID:
id_10 <- data[Cust_Id == 10]
id_10的测试费用:
shapiro.test(id_10$Expense)
循环它们:
for(i in unique(data$Cust_Id))
u <- setDT(data)[Cust_Id == i]
s <- shapiro.test(u$Expense)
print(i)
print(s)
或者创建子集,然后对每个子集应用测试:
for(i in unique(data$Cust_Id))
assign(paste0("id",i),setDT(data)[Cust_Id== i])
另一种方法是按唯一 id 分割:
z<-split(data,data$Cust_Id)
for(i in z)print(shapiro.test(i$Expense))
编辑
在表格中获取结果:
使用示例表:
x <- data.frame(a=c(1,1,1,2,2,2,3,3,3,4,4,4),y=c(100,10,20,20,35,50,1,2,3,4,5,100),z=c(1,2,3,4,5,6,7,8,9,10,11,12))
df <- setDT(x)[, .(Normality_y = shapiro.test(y), Normality_z = shapiro.test(z), Count = .N), by = a]
df 将在末尾显示 y 和 z 列的正态性以及唯一 ID 的计数。请注意,对于每个 ID,normality_y 数据框中的第一个数字是 W 值,第二个是 p 值。
要清理它:
library(plyr)
df2 <- ddply(df, "a", function(z) head(z,2))
现在,对于每个 ID,您将有两行分别代表 W 和 p 值。我使用了 y 和 z 列,您可以将它们更改为费用和收入等。添加更多列的语法应该直截了当
【讨论】:
R 没有采用 $ 值。我尝试使用您的代码,但它不起作用。错误是“意外的'$'”。我删除了 $ 并使用了 data["Cust_Id"],然后再次收到错误“当 i 是 data.table(或字符向量)时,x 必须键入(即已排序,并且,标记为已排序)”。我对数据框进行了排序,但又出现了同样的错误。 我将您的示例数据复制到了 excel 中。使用空格分隔符将其拆分为更多列。然后将其复制并通过执行以下操作将其放入 R:x 不要使用Expense($)
作为列名。在示例中很明显,OP 正在帮助我们了解它所持有的数据类型。在他们的示例数据框中,您可以看到列标题,包括Expense
。
我会编辑我的答案以反映您添加的示例数据
是的@Oli,我已经检查过了。我的数据集是一个数据表。我使用了您修改后的代码,但仍然没有得到任何结果。以上是关于使用 R 计算数据集中每个组的正态性的主要内容,如果未能解决你的问题,请参考以下文章
R语言Kolmogorov-Smirnov假设检验(正态性检验):检验数据的正态性