基于列名的第一个字母的子集数据框

时间:2014-02-10 14:31:46

标签: r subset

我有一个大型数据框,其中多列代表不同个体的不同变量。列的名称始终以数字开头(例如1:18)。我想将df分组并为每个人创建separete dfs。这是一个例子:

x <- as.data.frame(matrix(nrow=10,ncol=18))
colnames(x) <- paste(1:18, 'col', sep="")

我的真实df的列名是个人ID,变量名和度量数的组合(我对每个变量采取了3个度量)。因此,例如,我有个人1的度量b(正文),然后在df我将有3列名为:1b1,1b2,1b3。最后我有10个不同的区域(身体,头部,尾部,尾巴,背部,侧腹,腹部,喉部,前臂,腿部)。因此,对于每个人,我有30列(10个区域x每个区域3个度量)。所以我有多个变量以不同的数字开头,我想根据它们的唯一数字进行子集化。我尝试使用grep:

partialName <- 1
df2<- x[,grep(partialName, colnames(x))]
colnames(x)
[1] "1col" "2col" "3col" "4col" "5col" "6col" "7col" "8col" "9col" "10col" 
"11col" "12col" "13col" "14col" "15col" "16col" "17col" "18col"

我的问题在这里你可以看到它并没有将个体分开,因为1和10在子集中。换句话说,这会选择以1开头的所有人。 最终我想要做的就是遍布所有人(1:18),为每个人创建新的dfs。

2 个答案:

答案 0 :(得分:1)

我认为将数据保存在一个data.frame中是最佳选择。要么是这样,要么把它放到data.frame的列表中。这样可以更轻松地轻松提取每个人的摘要统计信息。

首先创建一些示例数据:

df = as.data.frame(matrix(runif(50 * 100), 100, 50), stringsAsFactors = FALSE)
names_variables = c('spam', 'ham', 'shrub')
individuals = 1:100
column_names = paste(sample(individuals, 50), 
                     sample(names_variables, 50, TRUE), 
                     sep = '')
colnames(df) = column_names

我首先要做的是使用melt将数据从宽格式转换为长格式。这基本上将所有列堆叠在一个大向量中,并添加一个额外的列,告诉它来自哪个列:

library(reshape2)
df_melt = melt(df)
head(df_melt)
  variable      value
1    85ham 0.83619111
2    85ham 0.08503596
3    85ham 0.54599402
4    85ham 0.42579376
5    85ham 0.68702319
6    85ham 0.88642715

然后我们需要将ID号与变量分开。这里的假设是变量的数字部分是单个ID,文本是变量名称:

library(dplyr)
df_melt = mutate(df_melt, individual_ID = gsub('[A-Za-z]', '', variable),
                          var_name = gsub('[0-9]', '', variable))

基本上删除不需要的部分字符串。现在我们可以做很多好事:

mean_per_indivdual_per_var = summarise(group_by(df_melt, individual_ID, var_name), 
                                       mean(value))
head(mean_per_indivdual_per_var)
  individual_ID var_name mean(value)
1            63     spam   0.4840511
2            46      ham   0.4979884
3            20    shrub   0.5094550
4            90      ham   0.5550148
5            30    shrub   0.4233039
6            21      ham   0.4764298

答案 1 :(得分:1)

您的colnames似乎是data.frame的标准版本,因此要获得第1列,您可以执行此操作:

df2 <- df[,1] #Where 1 can be changed to the number of column you wish.

无需按部分名称进行子集化。 虽然不建议您创建一个循环来执行此操作:

for (i in ncol(x)){
  assing(paste("df",i), x[,i]) #I use paste to get a different name for each column
}

虽然@paulhiemstra解决方案避免了循环。

因此,使用新信息,您可以按照自己的意愿使用grep,但具体说明您期望的匹配数量:

df2<- x[,grep("1{30}", colnames(x))]