基于数据帧中的另一个值重复数据帧中的行块

时间:2017-02-20 16:07:45

标签: r dataframe

这里有很多关于在R中重复预定次数的行的问题,但我无法找到一个来解决我要问的具体问题。

我有一个调查回复的数据框,其中每个受访者回答5到10个问题。作为一个玩具的例子:

df <- data.frame(ID = rep(1:2, each = 5),
             Response = sample(LETTERS[1:4], 10, replace = TRUE),
             Weight = rep(c(2,3), each = 5))

> df
   ID Response Weight
1   1        D      2
2   1        C      2
3   1        D      2
4   1        D      2
5   1        B      2
6   2        D      3
7   2        C      3
8   2        B      3
9   2        D      3
10  2        B      3

我想重复被访问者1的答案两次,作为一个块,然后被访者2的回答3次,作为一个块 ,我希望每个响应块都有一个唯一的ID。换句话说,我希望最终结果如下所示:

     ID Response Weight
1    11        D      2
2    11        C      2
3    11        D      2
4    11        D      2
5    11        B      2
6    12        D      2
7    12        C      2
8    12        D      2
9    12        D      2
10   12        B      2
11   21        D      3
12   21        C      3
13   21        B      3
14   21        D      3
15   21        B      3
16   22        D      3
17   22        C      3
18   22        B      3
19   22        D      3
20   22        B      3
21   23        D      3 
22   23        C      3
23   23        B      3
24   23        D      3
25   23        B      3

我这样做的方式目前真的笨重,并且,鉴于我的数据集中有>> 3000个受访者,速度难以忍受。

这是我的代码:

df.expanded <- NULL
for(i in unique(df$ID)) {
  x <- df[df$ID == i,]
  y <- x[rep(seq_len(nrow(x)), x$Weight),1:3]
  y$order <- rep(1:max(x$Weight), nrow(x))
  y <- y[with(y, order(order)),]
  y$IDNew <- rep(max(y$ID)*100 + 1:max(x$Weight), each = nrow(x))
  df.expanded <- rbind(df.expanded, y)
}

有更快的方法吗?

2 个答案:

答案 0 :(得分:1)

有一个更简单的解决方案。我想您希望根据代码中显示的add_filter('woocommerce_variation_price_html','prices_custom_labels', 10, 2 ); add_filter('woocommerce_price_html','prices_custom_labels', 10, 2 ); function prices_custom_labels( $price, $product ){ // Set HERE your custom labels names $per_dozen = ' '. __('per dozen', 'woocommerce' ); $per_case = ' '. __('per case (20 dozens)', 'woocommerce' ); // 1) Variable products if ($product->product_type != 'simple' && $product->variation_id ) { // Getting the array of existing attributes values for a variation $variation_attribute_value = $product->variation_data; // Here we keep only the last value in this array $last_variation_attribute_slug_value = ' ' . end($variation_attribute_value); // Finding the word 'case' in the attribute value slug $has_case = strstr($last_variation_attribute_slug_value, 'case'); // Setting the right displayed label depending on attribute value slug if( $has_case ) $attribute_quantity_name_value = $per_case; else $attribute_quantity_name_value = $per_dozen; // Here the output price + custom label $price = '<ins class="highlight">'.woocommerce_price( $product- >regular_price ).$attribute_quantity_name_value.'</ins>'; } // 2) Simple products else { // Here the output price + custom default label $price = '<ins class="highlight">'.woocommerce_price( $product- >regular_price ).$per_dozen.'</ins>'; } return $price; } 复制行。

Weight

这种方法更快吗?我们来看看:

df2 <- df[rep(seq_along(df$Weight), df$Weight), ]
df2$ID <- paste(df2$ID, unlist(lapply(df$Weight, seq_len)), sep = '')

# sort the rows
df2 <- df2[order(df2$ID), ]

可能还有其他更有效的方式。

答案 1 :(得分:1)

另一种方法是使用data.table

假设您从&#34; DT&#34;开始作为data.table,请尝试:

library(data.table)
DT[, list(.id = rep(seq(Weight[1]), each = .N), Weight, Response), .(ID)]

我还没有将ID列粘贴在一起,而是创建了一个辅助列。这对我来说似乎更灵活。

测试数据。更改n以创建要使用的更大数据集。

set.seed(1)
n <- 5
weights <- sample(3:15, n, TRUE)
df <- data.frame(ID = rep(seq_along(weights), weights),
                 Response = sample(LETTERS[1:5], sum(weights), TRUE),
                 Weight = rep(weights, weights))
DT <- as.data.table(df)