【问题标题】:Python and Pandas, find rows that contain value, target column has many sets of rangesPython和Pandas,查找包含值的行,目标列有很多组范围
【发布时间】:2021-01-17 01:56:23
【问题描述】:

我有一个凌乱的数据框,我试图在其中“标记”ids 列中包含特定数字的行。此列中的值表示一个包含范围:例如,“第 4 行”包含以下数字: 2409,2410,2411,2412,2413,2414,2377,2378,1478,1479,1480,1481,1482,1483,1484
在“第0行”和“第1行”其中一组的范围向后 (1931,1930,1929)

例如,如果我想知道哪些行的集合包含“2340”和“1930”,我该怎么做?我认为需要一个循环,有时需要查询的不仅仅是两个数字。使用 Python 3.8。

示例数据框

x = ['1331:1332,1552:1551,1931:1928,1965:1973,1831:1811,1927:1920',
     '1331:1332,1552:1551,1931:1929,180:178,1966:1973,1831:1811,1927:1920',
     '2340:2341,1142:1143,1594:1593,1597:1596,1310,1311',
     '2339:2341,1142:1143,1594:1593,1597:1596,1310:1318,1977:1974',
     '2409:2414,2377:2378,1478:1484',
     '2474:2476',
]
y = [6.48,7.02,7.02,6.55,5.99,6.39,]
df = pd.DataFrame(list(zip(x, y)), columns =['ids', 'val']) 
display(df)

所需的输出数据帧

【问题讨论】:

  • 您可以使用 apply 或 values 进行搜索
  • 对于每一行,您是在寻找 True 还是 False?如果找到这两个值,则为真?
  • 在这一行中,'2340:2341,1142:1143,1594:1593,1597:1596,1310,1311', 最后一个格式不同。这是正确的还是应该是:

标签: python-3.x pandas range


【解决方案1】:

我会编写一个执行两个步骤的函数:

  1. 给定包含 id 范围的 ids_string,将所有 id 列为ids_num_list
  2. 检查query_id是否在ids_num_list
def check_num_in_ids_string(ids_string, query_id):
    
    # Convert ids_string to ids_num_list
    ids_range_list = ids_string.split(',')
    ids_num_list = set()
    
    for ids_range in ids_range_list:
        
        if ':' in ids_range:
            lower, upper = sorted(ids_range.split(":"))
            num_list = list(range(int(lower), int(upper)+ 1))
            ids_num_list.update(num_list)
            
        else:
            ids_num_list.add(int(ids_range))
            
    # Check if query number is in the list
    
    if int(query_id) in ids_num_list:
        return 1
    
    else:
        return 0

# Example usage
query_id_list = ['2340', '1930']

for query_id in query_id_list:
    df[f'n{query_id}'] = (
        df['ids']
        .apply(lambda x : check_num_in_ids_string(x, query_id))
    )

返回你所需要的:

    ids                                                 val     n2340   n1930
0   1331:1332,1552:1551,1931:1928,1965:1973,1831:1...   6.48    0       1
1   1331:1332,1552:1551,1931:1929,180:178,1966:197...   7.02    0       1
2   2340:2341,1142:1143,1594:1593,1597:1596,1310,1311   7.02    1       0
3   2339:2341,1142:1143,1594:1593,1597:1596,1310:1...   6.55    1       0
4   2409:2414,2377:2378,1478:1484                       5.99    0       0
5   2474:2476                                           6.39    0       0

【讨论】:

  • 不存储到列表中,可以直接查看,找到就返回。试试if int(query_id) in range(int(lower),int(upper)+1): return 1。 else 语句相同。 if id_range == query_id: return 1。这将避免以后检查列表。当你退出 for 循环时,返回 0
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
相关资源
最近更新 更多