【问题标题】:Populate column in data frame based on a range found in another dataframe根据在另一个数据框中找到的范围填充数据框中的列
【发布时间】:2017-08-04 21:36:31
【问题描述】:

我正在尝试根据记录的索引值是否在另一个数据框中的两列定义的范围内来填充数据框中的列。

df1 看起来像:

    a
0   4
1   45
2   7
3   5
4   48
5   44
6   22
7   89
8   45
9   44
10  23

而 df2 是:

  START STOP CLASS
0   2   3   1
1   5   7   2
2   8   8   3

我想要的样子:

    a   CLASS
0   4   nan
1   45  nan
2   7   1
3   5   1
4   48  nan
5   44  2
6   22  2
7   89  2
8   45  3
9   44  nan
10  23  nan

df2 中的 START 列是范围的最小值,STOP 列是最大值。

【问题讨论】:

  • 欢迎来到 Stackoverflow。到目前为止,您尝试过什么?
  • 44怎么会有2的类值呢?它不在任何区间内?
  • groupbyreset_index 用于 df2,然后是 merge
  • CLASS 基于索引位置,而不是 a 列中的值。 a 列中的值 44 位于索引位置 5,属于 CLASS 2。

标签: python pandas


【解决方案1】:

您可以使用 IntervalIndex(需要 v0.20.0)。

首先构造索引:

df2.index = pd.IntervalIndex.from_arrays(df2['START'], df2['STOP'], closed='both')

df2
Out: 
        START  STOP  CLASS
[2, 3]      2     3      1
[5, 7]      5     7      2
[8, 8]      8     8      3

现在,如果您索引到第二个 DataFrame,它将在间隔中查找值。例如,

df2.loc[6]
Out: 
START    5
STOP     7
CLASS    2
Name: [5, 7], dtype: int64

返回第二类。我不知道它是否可以与 merge 或 merge_asof 一起使用,但作为替代方案,您可以使用 map:

df1['CLASS'] = df1.index.to_series().map(df2['CLASS'])

请注意,我首先将索引转换为 Series 以便能够使用 Series.map 方法。这导致

df1
Out: 
     a  CLASS
0    4    NaN
1   45    NaN
2    7    1.0
3    5    1.0
4   48    NaN
5   44    2.0
6   22    2.0
7   89    2.0
8   45    3.0
9   44    NaN
10  23    NaN

【讨论】:

  • 效果很好。谢谢!
【解决方案2】:

替代解决方案:


classdict = df2.set_index("CLASS").to_dict("index")

rangedict = {}

for key,value in classdict.items():

    # get all items in range and assign value (the key)
    for item in list(range(value["START"],value["STOP"]+1)):
        rangedict[item] = key

提取范围字典:

{2: 1, 3: 1, 5: 2, 6: 2, 7: 2, 8: 3}

现在映射和可能的格式(?):

df1['CLASS'] = df1.index.to_series().map(rangedict)
df1.applymap("{0:.0f}".format)

输出:

a   CLASS
0   4   nan
1   45  nan
2   7   1
3   5   1
4   48  nan
5   44  2
6   22  2
7   89  2
8   45  3
9   44  nan
10  23  nan

【讨论】:

    【解决方案3】:
    import pandas as pd
    import numpy as np
    
    # Here is your existing dataframe
    df_existing = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
    
    # Create a new empty dataframe with specific column names and data types
    df_new = pd.DataFrame(index=None)
    columns = ['field01','field02','field03','field04']
    dtypes = [str,int,int,int]
    for c,d in zip(columns, dtypes):
        df_new[c] = pd.Series(dtype=d)
    
    # Set the index on the new dataframe to same as existing 
    df_new['new_index'] = df_existing.index
    df_new.set_index('new_index', inplace=True)
    
    # Fill the new dataframe with specific fields from the existing dataframe
    df_new[['field02','field03']] = df_existing[['B','C']]
    print df_new
    

    【讨论】:

      猜你喜欢
      • 2016-02-14
      • 1970-01-01
      • 1970-01-01
      • 2017-02-10
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      相关资源
      最近更新 更多