【问题标题】:Python Pandas - Compare 2 dataframes, multiple parametersPython Pandas - 比较 2 个数据帧,多个参数
【发布时间】:2016-01-27 01:58:52
【问题描述】:

我有两张桌子。一个(下面的 df)大约有 18,000 行,另一个(下面的地图文件)有大约 800,000 行。我需要一个可以处理如此大的 DataFrame 的解决方案。

这是一个玩具示例: 表 1 - df

Sample    Chr    Start     End    Value
S1        1       100      200     1
S1        2       200      250     1
S2        1       50        75     5
S2        2       150      225     4

表 2 - 映射文件

Name    Chr    Position
P1       1      105
P2       1      60
P3       1      500
P4       2      25
P5       2      220
P6       2      240

我正在尝试执行以下操作(我的语法错误,但我认为这个想法出现了):

for mapline in mapfile:
    for dfline in df:
       if df[dfline]['Chr'] == mapfile[mapline]['Chr']
           if mapfile[mapline]['Position'] > df[dfline]['Start'] & mapfile[mapline]['Position'] < df[dfline]['End']
                  newdf[['Name','Chr','Position','Value', 'Sample']] = pd.DataFrame([ mapfile[mapline]['Name'], mapfile[mapline]['Chr'], mapfile[mapline]['Position'], df[dfline]['Value'], df[dfline]['Sample'] ] )

言下之意: 我需要遍历 mapfile 中的每个项目(行),看看它的位置是否在 df 中每个 CHR 上的任何 START 和 END 之间。如果是,我需要将其添加到包含两个表中的 Name、Chr、Position、Sample 和 Value 字段的新文件中。

玩具数据输出表:

Name    Chr    Position    Value   Sample
P1       1      105         1       S1
P2       1      60          5       S2
P5       2      220         1       S1
P5       2      220         4       S2
P6       2      240         1       S1

到目前为止: 我已经有了上面的内容,并且一直在找出语法以在 python 中执行一般循环时遇到问题。但是,我的理解是,使用 pandas 或 NumPy 之类的包可能会更容易?请帮助我找到最有效的方法来执行此操作,并且在此过程中对语法提供一些帮助会很棒。

我尝试过的一些相关帖子但无法正常工作 What is the most efficient way to loop through dataframes with pandas? How to iterate over rows in a DataFrame in Pandas? Append column to pandas dataframe Conditionally fill column values based on another columns value in pandas

【问题讨论】:

  • 您能添加代码来生成玩具示例吗?另外,您能否列出该示例的最终输出?
  • @Divakar ,我不知道如何编写代码以在 python 中生成示例。对不起。但我会在我到达计算机后立即添加最终输出。

标签: python numpy pandas


【解决方案1】:

IIUC 你可以使用read_csvmerge

import pandas as pd
import io

temp1=u"""Sample;Chr;Start;End;Value
S1;1;100;200;1
S1;2;200;250;1
S2;1;50;75;5
S2;2;150;225;4"""
#after testing replace io.StringIO(temp1) to filename
dfline = pd.read_csv(io.StringIO(temp1), sep=";")

temp2=u"""Name;Chr;Position
P1;1;105
P2;1;60
P3;1;500
P4;2;25
P5;2;220
P6;2;240"""
#after testing replace io.StringIO(temp2) to filename
mapfile = pd.read_csv(io.StringIO(temp2), sep=";")
print dfline
  Sample  Chr  Start  End  Value
0     S1    1    100  200      1
1     S1    2    200  250      1
2     S2    1     50   75      5
3     S2    2    150  225      4
print mapfile
  Name  Chr  Position
0   P1    1       105
1   P2    1        60
2   P3    1       500
3   P4    2        25
4   P5    2       220
5   P6    2       240

#merge by column Chr
df = pd.merge(dfline, mapfile, on=['Chr'])

#select by conditions
df = df[(df.Position > df.Start) & (df.Position < df.End)]

#subset of df
df =  df[['Name','Chr','Position','Value', 'Sample']]
print df
   Name  Chr  Position  Value Sample
0    P1    1       105      1     S1
4    P2    1        60      5     S2
7    P5    2       220      1     S1
8    P6    2       240      1     S1
10   P5    2       220      4     S2

#if you need reset index
print df.reset_index(drop=True)
  Name  Chr  Position  Value Sample
0   P1    1       105      1     S1
1   P2    1        60      5     S2
2   P5    2       220      1     S1
3   P6    2       240      1     S1
4   P5    2       220      4     S2

【讨论】:

  • 对我不起作用(我正在使用合并功能);输出有 0 行。数据类型必须相同吗?我担心我的不是。我使用 pandas.read_csv 函数导入了文件。
  • 您的数据框dflinemapfile 是像我这样的索引吗?尝试print dfline.index,输出为Int64Index([0, 1, 2, 3], dtype='int64')
  • 是的。输出为 Int64Index()
  • @GaiusAugustus 我猜merge 所针对的列必须具有相同的类型。您可以在其他 DataFrame 上执行类似 df1.Chr = df1.Chr.astype(int) 的操作,如果它们不一样的话。
  • @GaiusAugustus 您可以通过print dfline.dtypes, mapfile.dtypes 检查dtypes,然后如果Chr 列中的不同,请使用mgc 的评论。 @mgc 谢谢。
猜你喜欢
  • 2021-12-14
  • 1970-01-01
  • 2012-09-16
  • 2017-01-20
  • 2022-09-29
  • 1970-01-01
  • 2022-07-20
  • 2019-01-23
  • 1970-01-01
相关资源
最近更新 更多