如何使用.loc函数处理长度不匹配的情况

问题描述 投票:0回答:1

发布代码后会更容易解释问题。

这是我的前两个 dfs:

df_data1 = {
    "ID": [1, 2, 3, 4, 5],
    "Date": ['01-01-2010', '01-02-2010', '01-03-2010', '01-04-2010', '01-05-2010'],
    'Value': [90, 58, 85, 33, 68]
}

df_data2 = {
    "ID": [6, 7, 8, 9, 10],
    "Date": ['01-06-2010', '01-07-2010', '01-08-2010', '01-09-2010', '01-10-2010'],
    "Value": [85, 39, 99, 15, 87]
}

df1 = pd.DataFrame(df_data1)
df2 = pd.DataFrame(df_data2)

然后我使用交叉方法合并这两个,以便这两个 dfs 逐行比较。

df3 = df1.merge(df2, how="cross")
df3

然后我用两个索引创建第四个 df,所以我有一个整洁的 df,其中每一行都是两者之间的比较。

df4 = pd.DataFrame()
df4["Value"] = (df3[['Value_x', 'Value_y']].mean(axis=1))
df4.index = pd.MultiIndex.from_tuples(list(itertools.product(df1["ID"], df2["ID"])), names = ['df1 ID', 'df2 ID'])
df4

现在我遇到了麻烦。我想做的是添加列。一列显示第一个索引的日期,第二列显示第二个索引的日期。我认为 loc 将是最好使用的工具。这是我尝试使用的代码:

df4['df1 Date'] = df1.loc[df1['Date'] == df4.index.get_level_values(0)]['Date']
df4

这是错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-107-253564fdd003> in <module>
----> 1 df4['df1 Date'] = df1.loc[df1['Date'] == df4.index.get_level_values(0)]['Date']
      2 df4

~\AppData\Roaming\Python\Python37\site-packages\pandas\core\ops\common.py in new_method(self, other)
     67         other = item_from_zerodim(other)
     68 
---> 69         return method(self, other)
     70 
     71     return new_method

~\AppData\Roaming\Python\Python37\site-packages\pandas\core\arraylike.py in __eq__(self, other)
     30     @unpack_zerodim_and_defer("__eq__")
     31     def __eq__(self, other):
---> 32         return self._cmp_method(other, operator.eq)
     33 
     34     @unpack_zerodim_and_defer("__ne__")

~\AppData\Roaming\Python\Python37\site-packages\pandas\core\series.py in _cmp_method(self, other, op)
   5500 
   5501         with np.errstate(all="ignore"):
-> 5502             res_values = ops.comparison_op(lvalues, rvalues, op)
   5503 
   5504         return self._construct_result(res_values, name=res_name)

~\AppData\Roaming\Python\Python37\site-packages\pandas\core\ops\array_ops.py in comparison_op(left, right, op)
    260         if len(lvalues) != len(rvalues):
    261             raise ValueError(
--> 262                 "Lengths must match to compare", lvalues.shape, rvalues.shape
    263             )
    264 

ValueError: ('Lengths must match to compare', (5,), (25,))

我明白为什么会出现错误,但我不知道如何克服它。它误解了我的意图。我并不是想将 25 行与 5 行进行比较;每当该 ID 出现在该特定索引中时,我都会尝试在新列中显示 df1 的日期。

解决此问题后,我计划对第二个索引执行相同的操作,然后最终添加第三列来减去两个日期,以便它可以测量两个日期之间经过的时间。如果您知道一个好的、简洁的代码,我也会很有帮助,但我也可以自己做。

谢谢!

python pandas valueerror
1个回答
0
投票

我会保持简单,避免中间体,并且

itertools

out = (df1
 .merge(df2, how='cross', suffixes=['_df1', '_df2'])
 .set_index(['ID_df1', 'ID_df2'])
 .assign(Value=lambda d: d.pop('Value_df1').add(d.pop('Value_df2')).div(2))  
)

替代方案:

out = (df1
 .merge(df2, how='cross', suffixes=['_df1', '_df2'])
 .set_index(['ID_df1', 'ID_df2'])
 .assign(Value=lambda d: d[['Value_df1', 'Value_df2']].mean(axis=1))
 .drop(columns=['Value_df1', 'Value_df2'])
)

注意。如果您确实想要

df1
/
df2
作为前缀而不是后缀,请
rename
或使用正则表达式来后处理名称。

输出:

                 Date_df1    Date_df2  Value
ID_df1 ID_df2                               
1      6       01-01-2010  01-06-2010   87.5
       7       01-01-2010  01-07-2010   64.5
       8       01-01-2010  01-08-2010   94.5
       9       01-01-2010  01-09-2010   52.5
       10      01-01-2010  01-10-2010   88.5
2      6       01-02-2010  01-06-2010   71.5
       7       01-02-2010  01-07-2010   48.5
       8       01-02-2010  01-08-2010   78.5
       9       01-02-2010  01-09-2010   36.5
       10      01-02-2010  01-10-2010   72.5
3      6       01-03-2010  01-06-2010   85.0
       7       01-03-2010  01-07-2010   62.0
       8       01-03-2010  01-08-2010   92.0
       9       01-03-2010  01-09-2010   50.0
       10      01-03-2010  01-10-2010   86.0
4      6       01-04-2010  01-06-2010   59.0
       7       01-04-2010  01-07-2010   36.0
       8       01-04-2010  01-08-2010   66.0
       9       01-04-2010  01-09-2010   24.0
       10      01-04-2010  01-10-2010   60.0
5      6       01-05-2010  01-06-2010   76.5
       7       01-05-2010  01-07-2010   53.5
       8       01-05-2010  01-08-2010   83.5
       9       01-05-2010  01-09-2010   41.5
       10      01-05-2010  01-10-2010   77.5
© www.soinside.com 2019 - 2024. All rights reserved.