【问题标题】:Reshaping data based on different columns根据不同的列重塑数据
【发布时间】:2017-05-14 10:38:37
【问题描述】:

我有一个名为“inputdata”的数据集

Country Unknown Male Female Affected Male Female Unaffected Male Female
USA      200  120   80     130     80    50     70        40    30
AU       140  80    60     60      30    30     80        50    30

我将有两个输出数据集,如下所示,如您所见,输入数据集在这里有 3 个类别,如列名 2、5、8 中所述。

在输出 1 数据集中,Category 列具有类别,即输入数据中的列名。然后国家列和男性列中的国家将在输入中具有男性列的值。

类似地,在输出 2 数据集中,Category 和 Country 保持不变,但第 3 列 Actuals 应具有来自输入中相应类别的值,即第 2、5、8 列。

这里的关键是输入数据集结构保持不变。

Output 1

Category    Country Male 
Unknown      USA     120  
Affected     USA     80
Unaffected   USA     40
.
.
.

Output 2

Category    Country Actuals
Unknown      USA     200   
Affected     USA     130 
Unaffected   USA     70 
.
.
.

所以我现在所做的是,使用 for 循环使用索引对输入数据集中的每个类别进行子集化 --

例如,使用inputdata[,c(1,i)] 和我的'i' 变量将是3,6,9 for output 12,5,8 for output 2。然后创建一个数据框列表(每个类别一个)并将它们组合在一起以用于每个输出。我只是想知道是否有其他方法可以提高效率。

编辑:- 按要求添加我的代码,

for(i in seq(3, 9, by=3)) {
    if(!exists('mylist')) mylist <- NULL
    output1 <- inputdata[,c(1,i)]
    if(i==3) {
      output1$category <- 'unknown'
    } else if (i==6) {
      output1$category <- 'affected'
    } else
      output1$category <- 'unaffected'
    mylist <- c(mylist,output1)
    rm(output1)
  }


   for(i in seq(2, 8, by=3)) {
        if(!exists('mylist')) mylist <- NULL
        output2 <- inputdata[,c(1,i)]
        if(i==3) {
          output2$category <- 'unknown'
        } else if (i==6) {
          output2$category <- 'affected'
        } else
          output2$category <- 'unaffected'
        mylist <- c(mylist,output2)
        rm(output2)
      }

如果有什么不清楚的地方请告诉我。

【问题讨论】:

  • 请贴出您尝试过的代码。
  • 在此处添加。 :)
  • 但是你有同名的列。列名必须是唯一的。你可以在 R 中将该表加载为保留这些列名的 data.frame 吗?
  • 是的,我做到了。 R 允许使用 read_excel 函数从 excel 中读取它。
  • 读到R后我们甚至可以重命名为male1,male2,female1,female2。没问题。

标签: r reshape2 tidyr


【解决方案1】:

这是一个基本 R 方法,它使用 stack 根据特定列(即男性/女性、类别)转换为 long。

#data frame of categories - You can further split of country if needed 
# by split(d1, d1$country)

d1 <- data.frame(stack(df[-1][c(T, F, F)]), country = df$Country, stringsAsFactors = FALSE)

#  values        ind country
#1    200    Unknown     USA
#2    140    Unknown      AU
#3    130   Affected     USA
#4     60   Affected      AU
#5     70 Unaffected     USA
#6     80 Unaffected      AU

#create a list with two data frames (male and female)
#To split by country again, then lapply(l1, function(i) split(i, i$country))

l1 <- lapply(c('Male', 'Female'), function(i) setNames(data.frame(d1$ind, 
                                                 stack(df[grepl(i, names(df))])[-2],
                                                    df$Country, stringsAsFactors = F), 
                                              c('category', i, 'country')))

#[[1]]
#    category Male country
#1    Unknown  120     USA
#2    Unknown   80      AU
#3   Affected   80     USA
#4   Affected   30      AU
#5 Unaffected   40     USA
#6 Unaffected   50      AU

#[[2]]
#    category Female country
#1    Unknown     80     USA
#2    Unknown     60      AU
#3   Affected     50     USA
#4   Affected     30      AU
#5 Unaffected     30     USA
#6 Unaffected     30      AU

数据

dput(df)
structure(list(Country = c("USA", "AU"), Unknown = c(200L, 140L
), Male = c(120L, 80L), Female = c(80L, 60L), Affected = c(130L, 
60L), Male.1 = c(80L, 30L), Female.1 = c(50L, 30L), Unaffected = c(70L, 
80L), Male.2 = c(40L, 50L), Female.2 = c(30L, 30L)), .Names = c("Country", 
"Unknown", "Male", "Female", "Affected", "Male.1", "Female.1", 
"Unaffected", "Male.2", "Female.2"), row.names = c(NA, -2L), class = "data.frame")

【讨论】:

    猜你喜欢
    • 2018-05-27
    • 1970-01-01
    • 2011-03-29
    • 2022-01-07
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多