我有一个spotify数据集,里面有很多观察结果。
我在数据集上遇到的一个问题是,出现了很多(几乎)重复的观察结果。当一首歌有多种类型而不是只有一种类型时,就会发生这种情况,因为这会产生另一个与另一个相同的观察结果,只是genre
变量不同。在数据集中,一首歌曲可以有多达4种不同的类型,这会产生大量的冗余数据。
处理这种情况的最佳方法是什么?
我想做的:
我已经将分类genre
变量更改为虚拟变量,这在数据集中创建了额外的变量,每个类型一个。
接下来,我想为每首具有多种类型的独特歌曲求和虚拟变量,这样我就可以在之后删除(或分组)重复的观察结果,但我不确定如何处理这一部分。
模拟数据示例:
library(tidyverse)
library(fastDummies)
song_and_artist <- c("song_by_band", "song_by_band", "song_by_band", "othersong_by_otherband", "othersong_by_otherband")
genre <- c("pop", "rock", "hiphop", "rock", "pop")
popularity <- c(85, 85, 85, 58, 58)
df <- data.frame(song_and_artist,genre,popularity)
数据框看起来像这样:
> df
song_and_artist genre popularity
1 song_by_band pop 85
2 song_by_band rock 85
3 song_by_band hiphop 85
4 othersong_by_otherband rock 58
5 othersong_by_otherband pop 58
我将genre
变量转换为假人。
dummy_df <- df %>%
dummy_cols(select_columns = 'genre') %>%
select(-genre)
这就留下了一个像这样的数据框架:
> dummy_df
song_and_artist popularity genre_hiphop genre_pop genre_rock
1 song_by_band 85 0 1 0
2 song_by_band 85 0 0 1
3 song_by_band 85 1 0 0
4 othersong_by_otherband 58 0 0 1
5 othersong_by_otherband 58 0 1 0
从这个到这个的最好方法是什么:
> dummy_df
song_and_artist popularity genre_hiphop genre_pop genre_rock
1 song_by_band 85 1 1 1
2 othersong_by_otherband 58 0 1 1
我希望这能解释我的问题。
dummy_df %>%
group_by(song_and_artist, popularity) %>%
summarize(across(everything(), sum), .groups = "drop") # thanks Martin Gal!
或者我更喜欢:
dummy_df %>%
group_by(song_and_artist) %>%
summarize(across(-popularity, sum))
你可以试试
df %>%
pivot_wider(names_from = genre,
names_prefix = "genre_",
values_from = genre) %>%
mutate(across(starts_with("genre"), ~+!is.na(.)))
代替dummy_cols
。这将返回
# A tibble: 2 x 5
song_and_artist popularity genre_pop genre_rock genre_hiphop
<chr> <dbl> <int> <int> <int>
1 song_by_band 85 1 1 1
2 othersong_by_otherband 58 1 1 0
您想要实现的实际上与每首歌保留一行并删除genre
列相同。下面的文章已经非常详细地回答了如何做到这一点。https://stackoverflow.com/a/21553539/16240751
我们可以使用dcast
library(data.table)
dcast(setDT(df), song_and_artist + popularity ~ genre, length)
song_and_artist popularity hiphop pop rock
1: othersong_by_otherband 58 0 1 1
2: song_by_band 85 1 1 1