我有一个类似于以下内容的数据框:
virus_RNA specie id date
XXYGHS, ZZYRSC, Mk4RRE human 1 04.08.2010
XXYGHS, KRSTYC, ZZQERT human 2 02.06.2007
Mk4RRE, TTYCY3, WEQ478 bat 3 03.04.2002
Mk4RRE, XXYGHS, ZZQ478, 23RTYB rat 4 01.01.2001
VYsr67, XXYGHS, ZZQ478, 23RTYB rat 5 01.01.2001
XXYRTC, RTyy7u, MZrgTY human 6 01.03.2004
Mk4RRE, SfjB23, ZrtY6V, XXYGHS dog 7 01.12.1993
XXRSHS, KFK22C, ZZYRSC human 8 02.06.2003
我想实现两件事: 首先:我想计算在给定日期之前,物种中已观察到所有病毒RNA序列的次数,并创建一个新的数据框。例如,如果我们将第一行作为基准:
virus_RNA date human bat rat dog
XXYGHS 04.08.2010 1 0 2 1
ZZYRSC 04.08.2010 1 0 0 0
Mk4RRE 04.08.2010 0 1 1 1
第二:我需要回到原始数据框,并添加与病原体相同但与病原体不同的物种中每种病毒RNA以前所有出现的总和。遵循前面的示例:
Occurrence in human specie (as the focal specie) : XXYGHS and ZZYRSC have been observed in human while Mk4RRE has not been observed (1 + 1 + 0 = 2).
Occurrence in different species (different than the human) : bat (0 + 0 + 1 = 1); rat (2 + 0 + 1 = 3); dog (1 + 0 + 1= 2) and sum = 6
如果我们将其添加回原始数据框:
virus_RNA specie date same_specie different_specie id
XXYGHS, ZZYRSC, Mk4RRE human 04.08.2010 2 6 1
答案 0 :(得分:2)
[为了更好地回答您的问题而编辑,希望我不会引入任何错误!]
我认为我可以提供帮助。让我们首先生成DataFrame:
df = pd.DataFrame({"virus_RNA":
[
"XXYGHS, ZZYRSC, Mk4RRE" ,
"XXYGHS, KRSTYC, ZZQERT",
"Mk4RRE, TTYCY3, WEQ478",
"Mk4RRE, XXYGHS, ZZQ478, 23RTYB",
"VYsr67, XXYGHS, ZZQ478, 23RTYB ",
"XXYRTC, RTyy7u, MZrgTY",
"Mk4RRE, SfjB23, ZrtY6V, XXYGHS",
"XXRSHS, KFK22C, ZZYRSC",
],
"specie":
[
"human",
"human",
"bat",
"rat",
"rat",
"human",
"dog",
"human",
],
"date":
[
"04.08.2010",
"02.06.2007",
"03.04.2002",
"01.01.2001",
"01.01.2001",
"01.03.2004",
"01.12.1993",
"02.06.2003",
]
})
我要做的第一件事是为每个病毒RNA创建一行,因为我的答案将基于分组依据:
# Start by creating a list from the strings after having removed the spaces
df.loc[:, "virus_RNA"] = df.loc[:, "virus_RNA"].str.replace(" ", "").str.split(",")
# Explode: one row per element of the list (I changed the previous code to solve the memory error here please confirm this works)
df = df.explode("virus_RNA")
您将得到:
>>> df.head()
date specie virus_RNA
0 04.08.2010 human XXYGHS
1 04.08.2010 human ZZYRSC
2 04.08.2010 human Mk4RRE
3 02.06.2007 human XXYGHS
4 02.06.2007 human KRSTYC
然后给定您以后需要的焦点,我将添加一个带有焦点的物种名称的列,然后使用熊猫的get_dummies获得一热编码的specie变量版本。这样我们就可以按总和进行分组。
df["focal"] = df.loc[:, "specie"]
df = pd.get_dummies(df, columns=["specie"], prefix="", prefix_sep="")
这给我们:
>>> df.head()
date virus_RNA focal bat dog human rat
0 04.08.2010 XXYGHS human 0 0 1 0
1 04.08.2010 ZZYRSC human 0 0 1 0
2 04.08.2010 Mk4RRE human 0 0 1 0
3 02.06.2007 XXYGHS human 0 0 1 0
4 02.06.2007 KRSTYC human 0 0 1 0
现在我们可以做几个分组依据。 对于第一个问题,您可以按日期和总和进行分组,这将为您提供之前创建的假人的总和:
df.groupby(["virus_RNA", "date"]).sum()
具有以下输出:
>>> df.groupby(["virus_RNA", "date"]).sum().head()
bat dog human rat
virus_RNA date
23RTYB 01.01.2001 0 0 0 2
KFK22C 02.06.2003 0 0 1 0
KRSTYC 02.06.2007 0 0 1 0
MZrgTY 01.03.2004 0 0 1 0
Mk4RRE 01.01.2001 0 0 0 1
对于第二个问题,我将针对每种病毒RNA计算每个物种的病例数。为此,您可以将总和与分组,然后将其放回第一个数据帧:
df_grouped = df.groupby(["virus_RNA"]).sum().reset_index()
df = df.drop(columns=["bat", "dog", "human", "rat"]).merge(df_grouped, on="virus_RNA").drop_duplicates()
给出结果:
>>> df.head()
date virus_RNA focal bat dog human rat
0 04.08.2010 XXYGHS human 0 1 2 2
1 02.06.2007 XXYGHS human 0 1 2 2
2 01.01.2001 XXYGHS rat 0 1 2 2
4 01.12.1993 XXYGHS dog 0 1 2 2
5 04.08.2010 ZZYRSC human 0 0 2 0
我们可以通过删除日期并删除重复项来减少数据量,但是我们需要日期来重新创建初始数据框。
我们现在可以在数据帧上使用Apply为“ different_specie”创建一列,为“ same_specie”创建一列:
df["different_specie"] = df.apply(lambda row: sum([val for key, val in row.items()
if key not in ["virus_RNA", "date", "focal"]
and row["focal"] != key]),
axis=1)
df["same_specie"] = df.apply(lambda row: row[row["focal"]],
axis=1)
df = df.loc[:, ["virus_RNA", "focal", "different_specie", "same_specie", "date"]]
这给我们:
>>> df.head()
virus_RNA focal different_specie same_specie date
0 XXYGHS human 3 2 04.08.2010
1 XXYGHS human 3 2 02.06.2007
2 XXYGHS rat 3 2 01.01.2001
4 XXYGHS dog 4 1 01.12.1993
5 ZZYRSC human 0 2 04.08.2010
然后,我们需要重新创建初始数据框。我们可以按日期将日期分组,因为您的日期似乎是唯一的,但是随后我们需要连接virus_RNA,这将为我们提供一个缺少几列的临时数据框。然后,我们可以将其与第一个数据帧合并回去,并删除重复项。
temp = df.groupby(["date"])["virus_RNA"].apply(','.join).reset_index()
df = df.merge(temp, on="date").drop("virus_RNA_x", axis=1).drop_duplicates()
哪个给我们:
>>> df.head()
focal different_specie same_specie date virus_RNA_y
0 human 3 2 04.08.2010 XXYGHS,ZZYRSC,Mk4RRE
1 human 0 2 04.08.2010 XXYGHS,ZZYRSC,Mk4RRE
2 human 3 1 04.08.2010 XXYGHS,ZZYRSC,Mk4RRE
3 human 3 2 02.06.2007 XXYGHS,KRSTYC,ZZQERT
4 human 0 1 02.06.2007 XXYGHS,KRSTYC,ZZQERT
但是,virus_RNA中的顺序可能有所不同,您可以通过在开始时对ID进行排序和创建来克服它们。您还需要清除一些内容,例如virus_RNA_y名称。
要获取累计金额,您可以按日期排序,也可以按聚焦点和病毒rna分组:
df[["cumsum_different", "cumsum_same"]] = df.groupby(["virus_RNA_y", "focal"]).cumsum()
我认为您实际上不希望根据结果重新合并数据框?
我希望这会有所帮助。另外,这是我的第一个答案,希望这个网站的格式和其他要求都可以。