【问题标题】:Counting number the occurrences of specific string at particular time in Pandas dataframe计算 Pandas 数据框中特定时间特定字符串的出现次数
【发布时间】:2020-04-08 02:23:40
【问题描述】:

我有一个类似于以下的数据框:

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

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    [编辑以更好地回答您的问题,希望我没有引入任何错误!]

    我想我能帮上忙。我们先生成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()
    

    我认为您实际上并不希望根据结果重新合并数据框?

    我希望这会有所帮助。另外,这是我在这里的第一个答案,我希望我的回答中这个网站的格式和其他要求都可以。

    【讨论】:

    • 您好@edyvedy13,您成功了吗?如果是这样,你能接受答案吗? :)
    • 我也在寻找问题第二部分的答复:)
    • 啊所以你需要回到DataFrame是吗?我会看看,但我认为我们可以按日期分组并连接病毒 RNA。我对内存错误感到惊讶,也许你有很多数据,你需要一种更轻松的方法,因为这里的数据至少与函数的时间重复
    • 新版pandas有爆炸方法:pandas.pydata.org/pandas-docs/stable/reference/api/…可以试试吗?
    • 确实它似乎解决了内存问题。只需要将数据添加回原始帧
    猜你喜欢
    • 2018-04-10
    • 2011-07-08
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多