[编辑以更好地回答您的问题,希望我没有引入任何错误!]
我想我能帮上忙。我们先生成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 创建一行,因为我的答案将基于 group by:
# 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
然后考虑到您稍后需要焦点,我将添加一个带有焦点物种名称的列,然后使用来自 pandas 的 get_dummies 来获取物种变量的一次性编码版本。这样我们就可以按总和进行分组。
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 的每个物种的病例数。为此,您可以通过 group by 获得总和并将其放回第一个数据框:
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()
我认为您实际上并不希望根据结果重新合并数据框?
我希望这会有所帮助。另外,这是我在这里的第一个答案,我希望我的回答中这个网站的格式和其他要求都可以。